-
Notifications
You must be signed in to change notification settings - Fork 108
Expand file tree
/
Copy pathquery-profiles.html
More file actions
479 lines (434 loc) · 18.8 KB
/
query-profiles.html
File metadata and controls
479 lines (434 loc) · 18.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
---
# Copyright Vespa.ai. All rights reserved.
title: "Query Profiles"
redirect_from:
- /en/query-profiles.html
---
<p>
A Query Profile is a named collection of search request parameters given in the configuration.
The search request can specify a query profile
whose parameters will be used as parameters of that request.
This frees the client from having to manage and send a large number of parameters,
and enables the request parameters to use for a use case to be changed
without having to change the client.
Query profiles enables <a href="../applications/testing.html#feature-switches-and-bucket-tests">bucket tests</a>,
where a part of the query stream is given some experimental treatment,
as well as differentiating behavior based on (OEM) customer, user type, region, frontend type etc.
This document explains how to create and use query profiles.
See also the <a href="../reference/querying/query-profiles.html">query profile reference</a> for the full syntax.
</p>
<h2 id="using-a-query-profile">Using a Query Profile</h2>
<p>
A Query Profile is an XML file containing the request parameter names and their values, e.g.:
</p>
<pre>
<query-profile id="MyProfile">
<field name="hits">20</field>
<field name="maxHits">2000</field>
<field name="unique">merchantid</field>
</query-profile>
</pre>
<p>
See the <a href="../reference/querying/query-profiles.html">query profile reference</a> for the full syntax.
{% include important.html content='Note that full property names must be used, aliases like
<code>input.query(...)</code> are only supported in requests and programmatic lookup.'%}
See the <a href="../reference/api/query.html">Query API reference</a>
for a list of the built-in query properties.
</p><p>
To deploy a query profile:
</p>
<ol>
<li>Create a file for the profile, using the format above,
having the name <em>[my-profile-name].xml</em>,
e.g. <em>MyProfile.xml</em> (replace any <code>/</code> in the name by <code>_</code>)</li>
<li>Put this in the directory <em>search/query-profiles</em> in
the <a href="../basics/applications.html">application package</a> root</li>
<li><a href="../basics/applications.html#deploying-applications">Redeploy</a> the application package</li>
</ol>
<p>
Any number of query profile files may be added to this directory.
If the query profiles contains errors, like incorrect syntax and/or infinite reference loops, deployment will fail.
</p><p>
To use a query profile in a query request, send the name of the profile as the parameter <code>queryProfile</code>:
</p>
<pre>
queryProfile=MyProfile
</pre>
<p>
If the request does not specify a query profile,
the profile named <code>default</code> will be used.
If no <code>default</code> profile is configured, no profile will be used.
If the queryProfile parameter is set but does not resolve to an existing profile,
an error message is returned.
Example, set default query timeout to 200ms for all queries not using a query profile:
</p>
<pre>
$ cat search/query-profiles/default.xml
<query-profile id="default">
<field name="timeout">0.2</field>
</query-profile>
</pre>
<p>
The query profile values (whether set from a configured query profile or by the request)
is available as <em>query properties</em>.
To look up a value from a <a href="../applications/searchers.html">Searcher component</a>, use:
</p>
<pre>
query.properties().get("myVariable")
</pre>
<p>
Note that property names are case-sensitive.
</p>
<h3 id="example">Example</h3>
<p>
Use a query profile to modify the YQL query string
using an <a href="../reference/querying/yql.html#in">IN</a> operator
and <a href="#local-substitution">local substitution</a> of <em>cities</em>:
</p>
<pre>{% highlight xml %}
<query-profile id="city-filter">
<field name="yql">select * from restaurant where userQuery() and city in (%{cities})</field>
<field name="cities">""</field>
</query-profile>
{% endhighlight %}</pre>
<p>
Use <a href="../reference/schemas/schemas.html#match">match: word</a> for the IN operator:</p>
<pre>
field city type string {
indexing: summary | index
match: word
}
</pre>
<p>An example query passing the values for the IN operator to be substituted into the YQL string:</p>
<pre>
$ vespa query \
queryProfile=city-filter \
cities='"berlin","paris"' \
query='what the user typed'
</pre>
<p>
With this, the application can use the <em>city-filter</em> query profile if there are cities in the filter,
if empty, use a <em>no-filter</em> query profile:
</p>
<pre>{% highlight xml %}
<query-profile id="no-filter">
<field name="yql">select * from restaurant where userQuery()</field>
</query-profile>
{% endhighlight %}</pre>
<pre>
$ vespa query \
queryProfile=no-filter \
query='what the user typed'
</pre>
<h3 id="overrides">Overrides</h3>
<p>
The parameter values set in <em>MyProfile.xml</em> will be used
as if they were present directly in the request.
If a parameter is present both directly in the request and in a profile,
the request value takes precedence by default.
Individual query profile field can be made to take priority by setting
the <a href="../reference/querying/query-profiles.html#overridable">overridable</a> attribute to <code>false</code>.
Example:
</p>
<pre>
<query-profile id="default">
<field name="timeout" <span class="pre-hilite">overridable="false"</span>>0.2</field>
</query-profile>
</pre>
<h2 id ="nested-structure">Nested Structure</h2>
<p>
To support structure in the set of request variables, a query profile
value may not be a string but a reference to another query profile.
In this case, the referenced query profile functions as a map
(or struct, if types are used, see below) in the referencing query profile.
The parameter names of the nested profile gets preceded by the name of the
reference variable and a dot. For example:
</p>
<pre>
<query-profile id="MyProfile">
<field name="hits">10</field>
<field name="unique">merchantid</field>
<span class="pre-hilite"><field name="user"><ref>MyUserProfile</ref></field></span>
</query-profile>
</pre>
<p>Where the referenced profile might look like:</p>
<pre>
<query-profile id="MyUserProfile">
<field name="age">20</field>
<field name="profession">student</field>
</query-profile>
</pre>
<p>If <code>MyProfile</code> is referenced in a query now, it will contain the variables</p>
<pre>
hits=10
unique=merchantid
user.age=20
user.profession=student
</pre>
<p>
References can be nested to provide a deeper structure,
producing variables having multiple dots.
The dotted variables can be overridden directly in the search request
(using the dotted name) just as other parameters.
</p><p>
Note that the id value of a profile reference can also be set in the request,
making it possible to choose not just the top level profile
but also any number of specific subprofiles in the request.
For example, the request can contain
</p>
<pre>
queryProfile=MyUserProfile&user=ref:MyOtherUserprofile
</pre>
<p>
to change the reference in the above example to some other subprofile.
Note the <code>ref:</code> prefix which is required to identify this
as setting user to a query profile referenced by id rather than setting it to a string.
</p>
<h2 id="inheritance">Inheritance</h2>
<p>
A query profile may inherit one or more other query profiles.
This is useful when there is some common set of parameters applicable to
multiple use cases, and a smaller set of parameters which varies between them.
To inherit another query profile, reference it as follows:
</p>
<pre>
<query-profile id="MyProfile" <span class="pre-hilite">inherits="MyBaseProfile"</span>>
…
</query-profile>
</pre>
<p>
The parameters of <code>MyBaseProfile</code> will be present when this
profile is used exactly as if they were explicitly written in this profile.
</p><p>
Multiple inheritance is supported by specifying multiple
space-separated profile ids in the inheritance attribute.
Order matters in this list - if a parameter is set in more than one of the inherited profiles,
the first one encountered in the depth first, left to right search order is used.
</p><p>
Parameters specified in the child query profile will always override the same parameters in an inherited one.
</p>
<h2 id="value-substitution">Value Substitution</h2>
<p>
Query profile values may contain substitution strings on the form
<code>%{property-name}</code>. Example:
</p>
<pre>
<query-profile id="MyProfile">
<field name="message">Hello %{world}!</field>
<field name="world">Earth</field>
</query-profile>
</pre>
<p>
The value returned by looking up <code>message</code> will be <em>Hello Earth!</em>.
</p>
<h3 id="global-resolution">Global resolution</h3>
<p>
Values are normally replaced by the value returned
from <code>query.properties().get("property-name")</code> <em>at the time of the lookup</em>.
Therefore, substituted values may be looked up in variants, in inherited profiles,
in values set at run time and by following query profile references. Details:
</p>
<ul>
<li>No substitution will be performed <em>in</em> values set at run time</li>
<li>If the value referenced in a substitution returns null,
the reference is substituted by the empty string</li>
<li>Unclosed substitutions cause an error at deploy time, but unknown values do not
(they may exist at run time and will be replaced by an empty string if not)</li>
<li>Recursive substitution works as expected. However, there is no loop detection</li>
</ul>
<h3 id="local-substitution">Local substitution</h3>
<p>
To substitute by a value in the same query profile (or variant),
prefix the property by a dot, as in
</p>
<pre>
<query-profile id="MyProfile">
<field name="message">Hello %{<b>.</b>world}!</field>
<field name="world">Earth</field>
</query-profile>
</pre>
<p>
Local substitutions can be verified at deploy time and will cause an error if not found.
</p>
<h2 id="query-profile-variants">Query Profile Variants</h2>
<p>
In some cases, it is convenient to allow the values returned from a
query profile to vary depending on the values of some properties input in the request.
For example, a query profile may contain values which depend on both the market
in which the request originated (<code>market</code>), the kind of device (<code>model</code>)
<em>and</em> the bucket in question (<code>bucket</code>).
</p><p>
Such variants over a set of request parameters may be represented in a single query profile,
by defining nested variants of the query profile for the relevant combinations of request values.
A complete example:
</p>
<pre>
<query-profile id="multiprofile1"> <!-- A regular profile may define "virtual" children within itself -->
<!-- Names of the request parameters defining the variant profiles of this. Order matters as described below.
Each individual value looked up in this profile is resolved from the most specific matching virtual
variant profile -->
<dimensions>region,model,bucket</dimensions>
<!-- Values may be set in the profile itself as usual, this becomes the default values given no matching
virtual variant provides a value for the property -->
<field name="a">My general a value</field>
<!-- The "for" attribute in a child profile supplies values in order for each of the dimensions -->
<query-profile for="us,nokia,test1">
<field name="a">My value of the combination us-nokia-test1-a</field>
</query-profile>
<!-- Same as [us,*,*] - trailing "*"'s may be omitted -->
<query-profile for="us">
<field name="a">My value of the combination us-a</field>
<field name="b">My value of the combination us-b</field>
</query-profile>
<!-- Given a request which matches both the below, the one which specifies concrete values to the left
gets precedence over those specifying concrete values to the right
(i.e the first one gets precedence here) -->
<query-profile for="us,nokia,*">
<field name="a">My value of the combination us-nokia-a</field>
<field name="b">My value of the combination us-nokia-b</field>
</query-profile>
<query-profile for="us,*,test1">
<field name="a">My value of the combination us-test1-a</field>
<field name="b">My value of the combination us-test1-b</field>
</query-profile>
</query-profile>
</pre>
<h3 id="variants-and-inheritance">Variants and Inheritance</h3>
<p>
It is possible to define variants across several levels in an inheritance hierarchy.
The variant dimensions are inherited from parent to child,
with the usual precedence rules (depth first left to right),
so a parent profile may define the dimensions and the child the values over which it should vary.
</p><p>
Variant resolution within a profile has precedence over resolution in parents.
This means e.g. that a default value for a given property in a sub-profile will be chosen
over a perfect variant match in an inherited profile.
</p><p>
Variants may specify their own inherited profiles, as in:
</p>
<pre>
<query-profile id="multiprofile1">
…
<query-profile for="us,nokia,test1" inherits="parent1 parent2">
…
</query-profile>
</query-profile>
</pre>
<p>
Values are resolved in this profile and inherited profiles "interleaved" by the variant resolution order
(which is specificity by default). E.g. by decreasing priority:
</p>
<pre>
1. Highest prioritized variant value
2. Value in inherited from highest prioritized variant
3. Next highest prioritized variant value
4. Value in inherited from next highest prioritized variant
…
n. Value defined at top level in profile
n+1. Value in inherited from query profile
</pre>
<h2 id="query-profile-types">Query Profile Types</h2>
<p>
The query profiles may optionally be <em>type checked</em>.
Type checking is turned on by referencing a <em>Query Profile Type</em> from the query profile.
The type lists the legal set of parameters of the query profile,
whether additional parameters are allowed, and so on.
</p><p>
A query profile type is referenced by:
</p>
<pre>
<query-profile id="MyProfile" <span class="pre-hilite">type="MyProfileType"</span>>
…
</query-profile>
</pre>
<p>And the type is defined as:</p>
<pre>
<query-profile-type id="MyProfileType">
<field name="age" type="integer"/>
<field name="profession" type="string"/>
<field name="user" type="query-profile:MyUserProfile">
</query-profile-type>
</pre>
<p>
This specifies that these three parameters may be present in profiles using this type,
as well as the query profile type of the <code>user</code> parameter.
</p><p>
It is also possible to specify that parameters are mandatory,
that no additional parameters are allowed (strict),
to inherit other types and so on, refer to the full syntax in
<a href="../reference/querying/query-profiles.html#query-profile-types">the query profile reference</a>.
If the base profile type is strict, it <em>must</em> extend a built-in query profile type,
see the <a href="../reference/querying/query-profiles.html#strict">strict reference documentation</a>.
</p><p>
A query profile type is deployed by adding a file named <em>[query-profile-type-name].xml</em>
in the <em>search/query-profiles/types</em> directory in the application package.
</p><p>
Query profile types may be useful even if query profiles are not used to set values.
As they define the names, types and structure of the parameters which can be accepted in the search request,
they can also be used to define, restrict and check the content of search requests.
For example, as the built-in search api parameters are also type checked if a typed query profile is used,
types can be used to restrict the parameters that can be set in a request,
or to mandate that some are always set.
The built-in parameters are defined in a set of query profile types which are always present
and which can be inherited and referenced in application-defined types.
These built-in types are defined in the <a href="../reference/api/query.html">Query API</a>.
</p>
<h2 id="path-patching">Path Matching</h2>
<p>
By adding <code><match path="true"></code> to a profile type,
<em>path</em> name matching is used rather than the default exact matching
when a profile is looked up from a name.
Path matching interprets the profile name as a slash separated path
and matches references which are subpaths (more specific paths) to super-paths.
The most specific match becomes the target of the reference. For example:
</p>
<pre>
Given the query profile names:
a1
a1/b1
Then:
a1/b1/c1/d1 resolves to a1/b1
a1/b resolves to a1
a does not resolve
</pre>
<p>
This is useful to assign specific query profile id's to every client or bucket
without having to create a different configuration item for each of these cases.
If there is a need to provide a differentiated configuration for any such client or bucket in the future,
this can be done without having the client change its request parameter because a specific id is already used.
</p>
<h2 id="versioning">Versioning</h2>
<p>
Query profiles (and types) may exist in multiple versions at the same time.
Wherever a name of a query profile (or type) is referenced,
the name may also append a version string, separated by a colon, e.g <code>MyProfile:1.2.3</code>.
The version number is <em>resolved</em> - if no version is given the highest version known is used.
If the version number is only partially specified, as in <code>my-version:1</code>,
the highest version starting by 1 is used.
</p><p>
Where a query profile (or type) is defined, the id may specify the version, followed by a colon:
</p>
<pre>
<query-profile id="MyProfile<strong>:1.2.3</strong>">
…
</query-profile>
</pre>
<p>
Any sub-number omitted is taken to mean 0 where a version is defined,
so <code>id="MyProfile:1"</code> is the same as <code>"id=MyProfile:1.0.0"</code>.
</p><p>
Query profiles (and types) which specifies a version in their id
must use a file name which includes the same version string after the name,
separated by a dash, e.g. <em>MyProfile-1.2.3.xml</em>.
</p><p>
For more information on versions,
see <a href="../reference/applications/components.html#component-versioning">component versioning</a>.
</p>
<h2 id="dump-tool">Dump Tool</h2>
<p>
It can sometimes be handy to be able to dump resolved query profiles offline.
Run without arguments to get usage:
</p>
<pre>
$ <a href="../reference/operations/tools.html#vespa-query-profile-dump-tool">vespa-query-profile-dump-tool</a>
</pre>