Add colon after prefix when term starts with a colon
[xapian.git] / xapian-applications / omega / docs / termprefixes.rst
blob621f85416e1088bfe13dd7b9ef84110ada3b27e2
1 =============
2 Term Prefixes
3 =============
5 Xapian itself doesn't put any restrictions on the contents of a term, other
6 than that terms can't be empty, and there's an upper limit on the length
7 (which is backend dependent - glass allows 245 bytes, except that zero bytes
8 count double in this length).
10 However, Omega and ``Xapian::QueryParser`` impose some rules to aid
11 interoperability and make it easier to write code that doesn't require
12 excessive configuring.  It's probably wise to follow these rules unless
13 you have a good reason not to.  Right now you might not intend to use Omega
14 or the QueryParser, not to combine a search with another database.  But if
15 you later find you do, it'll be much easier if you're using compatible
16 rules!
18 The basic idea is that terms won't begin with a capital letter (since they're
19 usually lower-cased and often stemmed), so any term which starts with a capital
20 letter is assumed to have a prefix.  For all letters apart from X, this is a
21 single character prefix and these have predefined standard meanings (or are
22 reserved for standard meanings but currently unallocated).
24 X starts a multi-capital letter user-defined prefix.  If you want a prefix for
25 something without a standard prefix, you create your own starting with an X
26 (e.g. XSHOESIZE).  The prefix ends with the first non-capital.  If the term
27 you're prefixing starts with a capital letter or ":", add a ":" between prefix
28 and term to resolve ambiguity about where the prefix ends and the term begins.
30 Here's the current allocation list:
33         Author
35         Topic (mnemonic: what the document is aBout)
37         Date (numeric format: YYYYMMDD or "latest" - e.g. D20050224 or Dlatest)
39         Extension (folded to lowercase - e.g. Ehtml, or E for no extension)
41         Filename
43         newsGroup (or similar entity - e.g. a web forum name)
45         Hostname
47         boolean filter term for "can see" permission (mnemonic: Include)
49         Site term (mnemonic: Jumping off point)
51         Keyword
53         ISO Language code
55         Month (numeric format: YYYYMM)
57         ISO couNtry code (or domaiN name)
59         Owner
61         Pathname
63         uniQue id
65         Raw (i.e. unstemmed) term (unused by Xapian since 1.0.0)
67         Subject (or title)
69         mimeType
71         full URL of indexed document - if the resulting term would be > 240
72         bytes, a hashing scheme is used to prevent overflowing
73         the Xapian term length limit (see omindex for how to do this).
75         boolean filter term for "can't see" permission (mnemonic: grep -v)
77         longer prefix for user-defined use
79         year (four digits)
81         stemmed term
83 Reserved but currently unallocated: CW
85 There are two main uses for prefixes - boolean filters and probabilistic
86 (i.e. free text) fields.
88 Boolean Filters
89 ===============
91 If the documents being indexed describe objects in a museum, you might
92 have a 'material' field, which records what each object is primarily made of.
93 So a sundial might be 'material=Stone', a letter might be 'material=paper',
94 etc.  There's no standard prefix for 'material', so you might allocate ``XM``.
95 If you lowercase the field contents, you can avoid having to add a colon to
96 separate the prefix and content, so documents would be indexed by terms such as
97 ``XMstone``` or ``XMpaper``.
99 If you're indexing using scriptindex, and have a field in the input file
100 such as "material=Stone", and then your index script would have a rule
101 such as::
103     material : lower boolean=XM
105 You can then restrict a search in Omega by passing a B parameter with one
106 of these as the value, e.g. ``B=XMstone``
108 In your HTML search form, you can allow the user to select this using a set of
109 radio buttons::
111     Material:<br>
112     <input type="radio" name="B" value=""> Any<br>
113     <input type="radio" name="B" value="XMpaper"> Paper<br>
114     <input type="radio" name="B" value="XMstone"> Stone<br>
116 If you want to have multiple sets of radio buttons for selecting different
117 boolean filters, you can make use of Omega's preprocessing of CGI parameter
118 names by calling them "B 1", "B 2", etc (names are truncated at the first
119 space - see `cgiparams.html <cgiparams.html>`_ for full details).
121 You can also use a select tag::
123     Material:
124     <select name="B">
125     <option value="">Any</option>
126     <option value="XMpaper">Paper</option>
127     <option value="XMstone">Stone</option>
128     </select>
130 Or if you want the user to be able to select more than one material to filter
131 by, you can use checkboxes instead of radio buttons::
133     Material:<br>
134     <input type="checkbox" name="B" value="XMpaper"> Paper<br>
135     <input type="checkbox" name="B" value="XMstone"> Stone<br>
137 Or a multiple select::
139     Material:
140     <select multiple name="B">
141     <option value="XMpaper">Paper</option>
142     <option value="XMstone">Stone</option>
143     </select>
145 These will work in the natural way - if no materials are selected, then no
146 filtering by material will happen; if multiple materials are selected, then
147 items made of any of the materials will match (in details, groups of filter
148 terms with the same prefix are combined with ``OP_OR``; then these groups
149 are combined with ``OP_AND``).
151 Or perhaps the museum records multiple materials per object - e.g. a clock
152 might be made of brass, glass and wood.  This can be handled smoothly too - you
153 can specify multiple material fields to scriptindex::
155     material=brass
156     material=glass
157     material=wood
159 You may then want multiple filters on material to be mean "find me objects
160 which contain **all** of these materials" (rather than the default meaning
161 of "find me objects which contain **any** of these materials") - to do this
162 you want to set ``XM`` as a non-exclusive prefix, which you do like so (this
163 needs Omega 1.3.4 or later)::
165     $setmap{nonexclusiveprefix,XM,true}
167 You can also allow the user to restrict a search with a boolean filter
168 specified in text query (e.g. ``material:paper`` -> ``XMpaper``) by adding this
169 to the start of your OmegaScript template::
171     $setmap{boolprefix,material,XM}
173 Multiple aliases are allowed::
175     $setmap{boolprefix,material,XM,madeof,XM}
177 This decoupling of internal and external names is also useful if you want
178 to offer search frontends in more than one language, as it allows the
179 prefixes the user sees to be translated.
181 If the user specified multiple filters in the query string, for example
182 `material:wood material:paper`, then these are combined using similar logic
183 to that used for filters specified by ``B`` CGI parameters, with terms with the
184 same prefixed combined with ``OP_OR`` by default, or ``OP_AND`` specified by
185 ``$setmap{nonexclusiveprefix,...}``.
187 Probabilistic Fields
188 ====================
190 Say you want to index the title of the document such that the user can
191 search within the title by specifying title:report (for example) in their
192 query.
194 Title has standard prefix S, so you'd generate terms as normal, but then
195 add an "S" prefix.  If you're using scriptindex, then you do this by
196 adding "index=S" to the scriptindex rule like so::
198     title : field=title index=S
200 You then need to tell Xapian::QueryParser that "title:" maps to an "S" prefix.
201 If you're using Omega, then you do so by adding this to your OmegaScript
202 template (at the start is best)::
204     $setmap{prefix,title,S}
206 Or if you're writing your own search frontend, like this::
208     Xapian::QueryParser qp;
209     qp.add_prefix("subject", "S");
210     // And similar lines for other probabilistic prefixes...
211     // And any other QueryParser configuration (e.g. stemmer, stopper).
212     Xapian::Query query = qp.parse_query(user_query_string);
214 You can add multiple aliases for a prefix (e.g. title and subject for S), and
215 the decoupling of "UI prefix" and "term prefix" means you can easily translate
216 the "UI prefixes" if you have frontends in different languages.
218 Note that if you want words from the subject to be found without a prefix, you
219 either need to generate unprefixed terms as well as the prefixed ones, or map
220 the empty prefix to both "" and "S" like so::
222     Xapian::QueryParser qp;
223     // Search both subject and body if no field is specified:
224     qp.add_prefix("", "");
225     qp.add_prefix("", "S");
226     // Search just the subject if 'subject:' is specified:
227     qp.add_prefix("subject", "S");
228     Xapian::Query query = qp.parse_query(user_query_string);