name
- name of the topic
web
- name of the web the topic is within
text
- the body text of the topic (without embedded meta-data)
META:FILEATTACHMENT
name
attr
path
size
user
rev
date
comment
META:TOPICPARENT
name
META:TOPICINFO
author
date
format
version
- topic version (integer)
META:TOPICMOVED
by
date
from
to
META:FORM
- the main form of the topic name
META:FIELD
- the fields in the form. name
- name of the field
title
- title of the field
value
- what is stored in the field
form
- name of the form the field is in (currently always equal to META:FORM.name)
attributes
- string stored in the attributes, like H
for hidden
META:PREFERENCE
name
value
versions
field to do so: versions
versions
).
META:TOPICPARENT
, META:TOPICINFO
etc - are structures which are indexed by keys. For example, META:TOPICINFO
has 4 entries, which are indexed by the keys author
, date
, format
and version
. META:FILEATTACHMENT
, META:FIELD
and META:PREFERENCE
are all arrays, which means they can have any number of records under them. Arrays are indexed by numbers - for example, the first entry in the META:FIELD
array is entry [0].
It's a bit clumsy having to type META:FILEATTACHMENT
every time you want to refer to the array of attachments in a topic, so there are some predefined aliases that make it a bit less typing: attachments
means the same as META:FILEATTACHMENT
info
means the same as META:TOPICINFO
parent
means the same as META:TOPICPARENT
. Note: parent
is itself a map; use parent.name
to access the name of the parent topic
moved
means the same as META:TOPICMOVED
form
means the same as META:FORM
, so to test if a topic has a form named 'UserForm' you test for "form.name ~ '*.UserForm'"
fields
means the same as META:FIELD
, You can also use the name of the form (the value of form.name
e.g. PersonForm
)
preferences
means the same as META:PREFERENCE
Syntax | Means | Examples |
---|---|---|
X |
refers to the field named X . |
info , META:TOPICMOVED , attachments , name . |
X.Y |
refers to the entry with the key Y in the structure named X . If X is an array of structure, then it returns an array made up from the Y entry of each member of the array. |
info.date , moved.by , META:TOPICPARENT.name , attachments.name |
X[query] |
refers to all the elements of the array X that match query. |
attachments[size>1024] , DocumentContainer[name!='Summary' AND value~'top secret'].value |
X[N] |
where X is an array and N is an integer number >= 0, gets the Nth element of the array X . Negative indices can be used to index the array from the end e.g. attachments[-1] to get the last attachment. |
attachments[3] |
X/Y |
accesses Y from the topic specified by the value of X . X must evaluate to a topic name |
parent.name/(form.name='ExampleForm') will evaluate to true if (1) the topic has a parent, (2) the parent topic has the main form type ExampleForm . |
{X} |
expands to the value of the configure setting {X}, if it is accessible, or '' otherwise |
only some configuration settings are available: {AccessControlACL}{EnableDeprecatedEmptyDeny} , {AccessibleCFG} , {AdminUserLogin} , {AdminUserWikiName} , {AntiSpam}{EmailPadding} , {AntiSpam}{EntityEncode} , {AntiSpam}{HideUserDetails} , {AntiSpam}{RobotsAreWelcome} , {AttachmentNameFilter} , {AuthRealm} , {AuthScripts} , {Cache}{Enabled} , {DefaultDateFormat} , {DefaultUrlHost} , {DenyDotDotInclude} , {DisplayTimeValues} , {EnableEmail} , {EnableHierarchicalWebs} , {FormTypes} , {HomeTopicName} , {LeaseLength} , {LeaseLengthLessForceful} , {LinkProtocolPattern} , {LocalSitePreferences} , {LoginNameFilterIn} , {MaxRevisionsInADiff} , {MinPasswordLength} , {NameFilter} , {NotifyTopicName} , {NumberOfRevisions} , {PluginsOrder} , {Plugins}{WebSearchPath} , {PluralToSingular} , {Register}{AllowLoginName} , {Register}{Approvers} , {Register}{DisablePasswordConfirmation} , {Register}{EnableNewUserRegistration} , {Register}{NeedApproval} , {Register}{NeedVerification} , {Register}{RegistrationAgentWikiName} , {ReplaceIfEditedAgainWithin} , {SandboxWebName} , {ScriptSuffix} , {ScriptUrlPath} , {Site}{Locale} , {SitePrefsTopicName} , {Stats}{TopContrib} , {Stats}{TopicName} , {Stats}{TopViews} , {SuperAdminGroup} , {SystemWebName} , {TemplateLogin}{AllowLoginUsingEmailAddress} , {TemplatePath} , {TrashWebName} , {UploadFilter} , {UseLocale} , {UserInterfaceInternationalisation} , {UsersTopicName} , {UsersWebName} , {Validation}{Method} , {WebMasterEmail} , {WebMasterName} , {WebPrefsTopicName} |
.
and []
expressions. As long as there is only one form in the topic, it will have the same effect as the fields
accessor.
If you use the name of a field (for example, LastName
) in the query without a . before it, that is taken to mean "the value of the field named this". This works if and only if the field name isn't the same as of the top level entry names or their aliases described above. For example, the following expressions will all evaluate to the same thing: Lastname
PersonForm.Lastname
Lastname.value
moved
or maybe parent
), you can prepend the name of the form followed by a dot, as shown in the last example. You cannot refer to fields that have
the same name as operators (e.g. AND
, not
etc)
Note: some search implementations have difficulty with expressions that rely
on database values to disambiguate the syntax of the expression. If you don't
get the expected result from a query search, then make sure all references
are fully qualified.
\
to include the following special characters:
Code | Meaning |
---|
\t |
tab |
\033 |
octal character code |
\x7f |
hexadecimal character code |
\x{1234} |
hexadecimal wide character code |
\\ |
a single \ |
\d
means \d
(unless the string is used as a regular expression, in which case it means any digit).
Name | Meaning |
---|---|
UNDEFINED |
The undefined value |
NOW |
The current time, in seconds since midnight on 1st Jan, 1970 |
NOW
is the same as now
.
Operator | Meaning | Example |
---|---|---|
= |
Left-hand side (LHS) exactly matches the value on the Right-hand side (RHS). | field = 'String' , age = 1 . Numbers and strings can be compared. |
!= |
Inverse of = . |
age = 2 |
~ |
wildcard match ('*' will match any number of characters, '?' will match any single character | "PersonForm.Surname ~ '*Smit?'") Note: Surname ~ 'Smith' is the same as Surname = 'Smith' |
=~ |
regular expression match, see RegularExpressions for details. | number =~ '^\d+$' |
< |
LHS is less than RHS. If both sides are numbers, the order is numeric. Otherwise it is lexical (applies to all comparison operators) | 5 < 4 |
> |
greater than | 4 > 5 |
<= |
less than or equal to | 2 <= 1 |
>= |
greater than or equal to | 2 >= 1 |
LC |
Converts string to lower case, Use for caseless comparisons. | lc 'XYZ' will yield 'xyz' |
UC |
Converts string to UPPER CASE. Use for caseless comparisons. | uc 'xyz' will yield 'XYZ' |
D2N |
Converts a string representing a date (expressed in one of the formats that Foswiki can parse) to a number of seconds since 1st Jan 1970. This is the format dates are stored in inside Foswiki, and you have to convert a string date using D2N before you can compare it with - for example - the date an attachment was uploaded. Times without a timezone are assumed to be in server local time. If the text string is not recognised as a valid date, then D2N will return undefined . |
d2n '25-Dec-2011' |
NOT |
Invert the result of the subquery | not(Size < 2) |
AND |
Combine two subqueries | (Length > Width) and (Age < Beauty) |
OR |
Combine two subqueries | (Length > Width) or (Age < Beauty) |
INT |
return the integer portion of a value (returns undef if the string isn't an integer, so beware.) | int SomeField or int -1.5 |
() |
Bracketed subquery | (Length > Width) |
, |
Array separator. | (1,2,3) expands to an array containing the scalar values [1,2,3] , If either side of this operator returns an array value, that array will be flattened into the result i.e. ((1,2),(3,4)) is equivalent to (1,2,3,4) |
+ |
Arithmetic addition, and string concatenation. String concatenation applies if either side of the expression does not evaluate to a number. | 1 + 2 |
- |
Arithmetic subtraction | 2 - 1 |
- |
Unary minus | -Size |
* |
Arithmetic multiplication | Buck * Doe |
DIV |
Arithmetic (real number) division | Rabbits div Stoats |
IN |
Test if a value is in a list | 1 in (2, 3, 4) |
AND
is the same as and
.
undefined
.
In the operators ( = != ~ =~ < > <= >= NOT AND OR
) an undefined operand is treated the same as numerical 0. For lc uc d2n
an undefined operand will give an undefined result. For length
and undefined operand will give a result of 0.
"attachments"
, then this will return TRUE for all topics that have one or more attachments. If I write "attachments[size>1024 AND name ~ '*.gif']"
then it will return TRUE for all topics that have at least one attachment larger than 1024 bytes with a name ending in .gif
.
type=query
search is always case sensitive, with the exceptions of: and
and AND
are the same)
now
and NOW
are the same)
lc()
or uc()
functions to convert either side of the comparison to be lower or upper case.
This is further demonstrated below in the examples.
,
operator inside the brackets to select a number of matching elements. For example,
versions[0,-1]will select the most recent version (stored at index 0) and the oldest version. You can even mix integer indices and conditions. For example, let's say we want to select all versions that are authored by 'RoaldDahl' and also select the oldest revision.
versions[-1,info.author='RoaldDahl']Note that if 'RoaldDahl' authored the first revision, then you will get that revision twice in the result. When the dot operator is applied to an array, it is applied to each element of the array, and the result is a new array containing the results of each application.
versions
field is mainly used with %QUERY
to provide a powerful view into the history of a topic. It is an array of objects, one for each revision of the topic (including the most recent), where the most recent revision is in position [0] in the array, and the second most recent in [1] etc. You can use the versions
field to select old versions based on a query. For example,
versions[info.author='RoaldDahl']will return a list of all versions authored by RoaldDahl. You can access field values in the topics as they were at the time - for example,
versions[info.author='RoaldDahl'].Publishedwill return an array of the values of the Published field in all versions authored by RoaldDahl. When you access the topic history using the
versions
field, the history of the topic is loaded with the most recent revision first i.e. at index [0]. So versions[1] does not refer to version 1 of the topic; it refers to the version at position 1 in the array i.e. one before the most recent revision. If you want to access the version numbered '1', then you must use versions[info.version=1]
(or versions[-1]
).
WARNING: Some of the Foswiki store implementations use an external tool called RCS
to store topic histories. RCS has very poor performance when it comes to recovering all versions. For this reason you should avoid use of queries that use versions
if you are using one of these stores.
Main.UserTopic/UserForm.firstName
because Main.UserTopic
will be interpreted as a form field name. If you want to refer to topics you must enclose the topic name in quotes i.e. 'Main.UserTopic'/UserForm.firstName
%INCLUDE
ed topic, where you might expect them to operate in the context of the including topic, rather than the included topic.
attachments[name='purdey.gif']
- true if there is an attachment call purdey.gif
on the topic
(fields[name='Firstname'].value='Emma' OR fields[name='Firstname'].value='John') AND fields[name='Lastname'].value='Peel'
- true for 'Emma Peel' and 'John Peel' but not 'Robert Peel' or 'Emma Thompson'
(Firstname='Emma' OR Firstname='John') AND Lastname='Peel'
- shortcut form of the previous query
HistoryForm[name='Age'].value>2
- true if the topic has a HistoryForm
, and the form has a field called Age
with a value > 2
HistoryForm.Age > 2
- shortcut for the previous query
preferences[name='FaveColour' AND value='Tangerine']
- true if the topic has the given preference settings and value
Person/(ClothesForm[name='Headgear'].value ~ '*Bowler*' AND attachments[name~'*hat.gif' AND date < d2n('2007-01-01')])
- true if the form attached to the topic has a field called Person
that has a value that is the name of a topic, and that topic contains the form ClothesForm
, with a field called Headgear
, and the value of that field contains the string 'Bowler'
, and the topic also has at least one attachment that has a name matching *hat.gif
and a date before 1st Jan 2007. (Phew!)
length(fields[NOT lc(attributes)=~'h'])
- the number of fields that are not hidden
lc(name)=~'.*ann.*'
- Would match Anne, Maryann, MaryAnn, AnnMarie...
%SEARCH{"parent.name='%TOPIC%' OR parent.name='%WEB%.%TOPIC%'" web="%WEB%" type="query"}%Find all topics that have an attachment called 'grunge.gif'
%SEARCH{"attachments[name='grunge.gif']" type="query"}%Find all topics that have form
ColourForm
where the form field 'Shades' is 'green' or 'yellow' but not 'brown'
%SEARCH{"(lc(Shades)='green' OR lc(Shades)='yellow') AND NOT(lc(Shades) ~ 'brown')" type="query"}%Find all topics that have PNG attachments that have been added since 26th March 2007
%SEARCH{"attachments[name ~ '*.png' AND date >= d2n('2007-03-26')]" type="query"}%Find all topics that have a field 'Threat' set to 'Amber' and 'cold virus' somewhere in the topic text.
%SEARCH{"Threat='Amber' AND text ~ '*cold virus*'" type="query"}%Find all topics newer than one week old
%SEARCH{"info.date >= %CALC{"$TIMEADD($TIME(), -7, day)"}%" type="query"}%Search for topic based upon browser input
%SEARCH{"lc(name)=~lc('.*%URLPARAM{"q"}%.*')" type="query"}%Related Topics: SearchHelp, VarSEARCH, FormattedSearch, QuerySearchPatternCookbook