Add note about DNS SRV records
[openafs-wiki.git] / TWiki / QuerySearch.mdwn
1 # <a name="Query Search"></a> Query Search
2
3 Query searches help you search the contents of forms attached to your topics, as well as the values of other meta-data attached to the topic. Using query searches you can search:
4
5 1. The fields of forms
6 2. Parent relationships
7 3. File attachment information (but **not** the attached files themselves)
8
9 Query searches are defined using a simple SQL-like query language. The language consists of _field specifiers_ and _constants_ joined with _operators_.
10
11 <div>
12   <ul>
13     <li><a href="#Query Search"> Query Search</a><ul>
14         <li><a href="#Field specifiers"> Field specifiers</a></li>
15         <li><a href="#Constants"> Constants</a></li>
16         <li><a href="#Operators"> Operators</a></li>
17         <li><a href="#Putting it all together"> Putting it all together</a></li>
18         <li><a href="#Gotcha"> Gotcha</a></li>
19         <li><a href="#Examples"> Examples</a><ul>
20             <li><a href="#Query examples"> Query examples</a></li>
21             <li><a href="#Search examples"> Search examples</a></li>
22           </ul>
23         </li>
24       </ul>
25     </li>
26   </ul>
27 </div>
28
29 ## <a name="Field specifiers"></a> Field specifiers
30
31 You use field specifiers to say what value from the topic you are interested in.
32
33 All meta-data in a topic is referenced according to a to a simple plan.
34
35 - `name` - name of the topic
36 - `web` - name of the web the topic is within
37 - `text` - the body text of the topic
38 - `META:FILEATTACHMENT`
39   - _for each attachment_
40     - `name`
41     - `attr`
42     - `path`
43     - `size`
44     - `user`
45     - `rev`
46     - `date`
47     - `comment`
48 - `META:TOPICPARENT`
49   - `name`
50 - `META:TOPICINFO`
51   - `author`
52   - `date`
53   - `format`
54   - `rev` - topic revision (`12`) to match `%REVINFO{'$rev'}%` and [[FormattedSearch]] `$rev`
55   - `version` - internal Store topic version (`1.12` for rcs based Stores)
56 - `META:TOPICMOVED`
57   - `by`
58   - `date`
59   - `from`
60   - `to`
61 - `META:FORM` - the main form of the topic
62   - `name` (known as the _formname_)
63 - `META:FIELD` - the fields in the form.
64   - _for each field in the form_
65     - `name`
66     - `title`
67     - `value`
68 - `META:PREFERENCE`
69   - _for each preference in the topic_
70     - `name`
71     - `value`
72
73 See [[TWikiMetaData]] for details of what all these entries mean.
74
75 Most things at the top level of the plan - `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.
76
77 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:
78
79 - `attachments` means the same as `META:FILEATTACHMENT`
80 - `info` means the same as `META:TOPICINFO`
81 - `parent` means the same as `META:TOPICPARENT`
82 - `moved` means the same as `META:TOPICMOVED`
83 - `form` means the same as `META:FORM`
84 - `fields` means the same as `META:FIELD`, You can also use the name of the form (the value of `form.name` e.g. `PersonForm`)
85 - `preferences` means the same as `META:PREFERENCE`
86
87 This plan is referenced using a simple syntax:
88
89 <table border="1" cellpadding="0" cellspacing="0">
90   <tr>
91     <th bgcolor="#99CCCC"><strong> Syntax </strong></th>
92     <th bgcolor="#99CCCC"><strong> Means </strong></th>
93     <th bgcolor="#99CCCC"><strong> Examples </strong></th>
94   </tr>
95   <tr>
96     <td><code>X</code></td>
97     <td> refers to the field named <code>X</code>. </td>
98     <td><code>info</code>, <code>META:TOPICMOVED</code>, <code>attachments</code>, <code>name</code>. </td>
99   </tr>
100   <tr>
101     <td><code>X.Y</code></td>
102     <td> refers to the entry with the key <code>Y</code> in the structure named <code>X</code></td>
103     <td><code>info.date</code>, <code>moved.by</code>, <code>META:TOPICPARENT.name</code></td>
104   </tr>
105   <tr>
106     <td><code>X[<i>query</i>]</code></td>
107     <td> refers to all the elements of the array <code>X</code> that match <em>query</em>. If <i>query</i> is of the form <code>name='Y'</code> then you can use the same <code>X.Y</code> syntax as is used for accessing structures. </td>
108     <td><code>attachments[size&gt;1024]</code>, <code>DocumentForm[name!='Summary' AND value~'top secret'].value</code>, <code>DocumentForm.Summary</code></td>
109   </tr>
110   <tr>
111     <td><code>X[N]</code></td>
112     <td> where <code>X</code> is an array and <code>N</code> is an integer number &gt;= 0, gets the Nth element of the array <code>X</code></td>
113     <td><code>attachments[3]</code></td>
114   </tr>
115   <tr>
116     <td><code>X/Y</code></td>
117     <td> accesses <code>Y</code> from the topic specified by the <em>value</em> of <code>X</code>. <code>X</code> must evaluate to a topic name </td>
118     <td><code>parent.name/(form.name='ExampleForm')</code> will evaluate to true if (1) the topic has a parent, (2) the parent topic has the main form type <code>ExampleForm</code>. </td>
119   </tr>
120 </table>
121
122 Note: at some point TWiki may support multiple forms in the same topic. For this reason you are recommended **not** to use the `fields` shortcut when accessing form fields, but always use the name of the form instead.
123
124 There is a shortcut for accessing form fields. 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:
125
126 - `PersonForm[name='Lastname'].value`
127 - `Lastname`
128 - `PersonForm.Lastname`
129
130 If `X` would conflict with the name of an entry or alias (e.g. it's `moved` or maybe `parent`), you can prepend the name of the form followed by a dot, as shown in the last example.
131
132 ## <a name="Constants"></a> Constants
133
134 You use constants for the values that you compare with fields. Constants are either strings, or numbers. Strings are always delimited by single-quotes (you can escape a quote using backslash). Numbers can be any integer or floating point number.
135
136 ## <a name="Operators"></a> Operators
137
138 Field specifiers and constants are combined using _operators_ to create queries.
139
140 <table border="1" cellpadding="0" cellspacing="0">
141   <tr>
142     <th bgcolor="#99CCCC"><strong> Operator </strong></th>
143     <th bgcolor="#99CCCC"><strong> Meaning </strong></th>
144   </tr>
145   <tr>
146     <td><code>=</code></td>
147     <td> Left-hand side (LHS) exactly matches the value on the Right-hand side (RHS). Numbers and strings can be compared. </td>
148   </tr>
149   <tr>
150     <td><code>!=</code></td>
151     <td> Inverse of <code>=</code>. </td>
152   </tr>
153   <tr>
154     <td><code>~</code></td>
155     <td> wildcard match ('*' will match any number of characters, '?' will match any single character e.g. "PersonForm.Surname ~ '*Smit?'") Note: Surname ~ 'Smith' is the same as Surname = 'Smith' </td>
156   </tr>
157   <tr>
158     <td><code>&lt;</code></td>
159     <td> LHS is less that RHS. If both sides are numbers, the order is numeric. Otherwise it is alphabetic (applies to all comparison operators) </td>
160   </tr>
161   <tr>
162     <td><code>&gt;</code></td>
163     <td> &gt; </td>
164   </tr>
165   <tr>
166     <td><code>&gt;=</code></td>
167     <td> &amp;gte; </td>
168   </tr>
169   <tr>
170     <td><code>&lt;=</code></td>
171     <td> &amp;lte; </td>
172   </tr>
173   <tr>
174     <td><code>lc(x)</code></td>
175     <td> Converts x to lower case, Use for caseless comparisons. </td>
176   </tr>
177   <tr>
178     <td><code>uc(x)</code></td>
179     <td> Converts x to UPPER CASE. Use for caseless comparisons. </td>
180   </tr>
181   <tr>
182     <td><code>d2n(x)</code></td>
183     <td> Converts a date (expressed in [[Main/TimeSpecifications]]) to a number of seconds since 1st Jan 1970. This is the format dates are stored in inside TWiki, and you have to convert a string date using <code>d2n</code> 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 you have date fields in your forms, note that they are <strong>not</strong> stored in TWiki's internal format, but are stored as text strings. You should still use <code>d2n</code> to convert them to numbers for comparisons, though. </td>
184   </tr>
185   <tr>
186     <td><code>NOT</code></td>
187     <td> Invert the result of the subquery </td>
188   </tr>
189   <tr>
190     <td><code>AND</code></td>
191     <td> Combine two subqueries </td>
192   </tr>
193   <tr>
194     <td><code>OR</code></td>
195     <td> Combine two subqueries </td>
196   </tr>
197   <tr>
198     <td><code>()</code></td>
199     <td> Bracketed subquery </td>
200   </tr>
201 </table>
202
203 %I% The same operators are supported for [[%IF statements|Main/VarIF]].
204
205 ## <a name="Putting it all together"></a> Putting it all together
206
207 When a query is applied to a topic, the goal is to reduce to a TRUE or FALSE value that indicates whether the topic matches that query or not. If the query returns TRUE, then the topic is included in the search results.
208
209 A query matches if the query returns one or more values when it is applied to the topic. So if I have a very simple query, such as `"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`.
210
211 ## <a name="Gotcha"></a> Gotcha
212
213 - Remember that in the query language, TWiki topic names are _constants_. You cannot write `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`
214
215 ## <a name="Examples"></a> Examples
216
217 ### <a name="Query examples"></a> Query examples
218
219 - `attachments[name='purdey.gif']` - true if there is an attachment call `purdey.gif` on the topic
220 - `(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'
221 - `(Firstname='Emma' OR Firstname='John') AND Lastname='Peel'` - shortcut form of the previous query
222 - `HistoryForm[name='Age'].value>2` - true if the topic has a `HistoryForm`, and the form has a field called `Age` with a value &gt; 2
223 - `HistoryForm.Age > 2` - shortcut for the previous query
224 - `preferences[name='FaveColour' AND value='Tangerine']` - true if the topic has the given preference setting and value
225 - <code>Person/([[ClothesForm]][name='Headgear'].value ~ '\*Bowler\*' AND attachments[name~'\*hat.gif' AND date &lt; d2n('2007-01-01')])</code> - 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!)
226
227 ### <a name="Search examples"></a> Search examples
228
229 Find all topics that are children of this topic in the current web
230
231     %SEARCH{"parent.name = '%TOPIC%'" web="%WEB%" type="query"}%
232
233 Find all topics that have an attachment called 'grunge.gif'
234
235     %SEARCH{"attachments[name='grunge.gif']" type="query"}%
236
237 Find all topics that have form `ColourForm` where the form field 'Shades' is 'green' or 'yellow' but not 'brown'
238
239     %SEARCH{"(lc(Shades)='green' OR lc(Shades)='yellow') AND NOT(lc(Shades) ~ 'brown')" type="query"}%
240
241 Find all topics that have PNG attachments that have been added since 26th March 2007
242
243     %SEARCH{"attachments[name ~ '*.png' AND date >= d2n('2007-03-26')"}%
244
245 Find all topics that have a field 'Threat' set to 'Amber' and 'cold virus' somewhere in the topic text.
246
247     %SEARCH{"Threat='Amber' AND text ~ '*cold virus*'"}%