Skip to content

Commit 7d70cb9

Browse files
Add distance feature query (#9582)
* Add distance feature query Signed-off-by: Fanit Kolchina <[email protected]> * Apply suggestions from code review Co-authored-by: Nathan Bower <[email protected]> Signed-off-by: kolchfa-aws <[email protected]> --------- Signed-off-by: Fanit Kolchina <[email protected]> Signed-off-by: kolchfa-aws <[email protected]> Co-authored-by: Nathan Bower <[email protected]> (cherry picked from commit 0c65cfd) Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
1 parent e8d4c4a commit 7d70cb9

File tree

1 file changed

+223
-0
lines changed

1 file changed

+223
-0
lines changed
+223
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
---
2+
layout: default
3+
title: Distance feature
4+
parent: Specialized queries
5+
nav_order: 5
6+
has_math: true
7+
---
8+
9+
# Distance feature query
10+
11+
Use the `distance_feature` query to boost the relevance of documents that are closer to a specific date or geographic point. This can help you prioritize more recent or nearby content in your search results. For example, you can assign more weight to products manufactured more recently or boost items closest to a user-specified location.
12+
13+
You can apply this query to fields containing date or location data. It's commonly used within a `bool` query `should` clause to improve relevance scoring without filtering out results.
14+
15+
## Configuring the index
16+
17+
Before using the `distance_feature` query, ensure that your index contains at least one of the following field types:
18+
19+
- [`date`]({{site.url}}{{site.baseurl}}/field-types/supported-field-types/date/)
20+
- [`date_nanos`]({{site.url}}{{site.baseurl}}/field-types/supported-field-types/date-nanos/)
21+
- [`geo_point`]({{site.url}}{{site.baseurl}}/field-types/supported-field-types/geo-point/)
22+
23+
In this example, you'll configure the `opening_date` and `coordinates` fields that you can use to run distance feature queries:
24+
25+
```json
26+
PUT /stores
27+
{
28+
"mappings": {
29+
"properties": {
30+
"opening_date": {
31+
"type": "date"
32+
},
33+
"coordinates": {
34+
"type": "geo_point"
35+
}
36+
}
37+
}
38+
}
39+
```
40+
{% include copy-curl.html %}
41+
42+
Add sample documents to the index:
43+
44+
```json
45+
PUT /stores/_doc/1
46+
{
47+
"store_name": "Green Market",
48+
"opening_date": "2025-03-10",
49+
"coordinates": [74.00, 40.70]
50+
}
51+
```
52+
{% include copy-curl.html %}
53+
54+
```json
55+
PUT /stores/_doc/2
56+
{
57+
"store_name": "Fresh Foods",
58+
"opening_date": "2025-04-01",
59+
"coordinates": [73.98, 40.75]
60+
}
61+
```
62+
{% include copy-curl.html %}
63+
64+
```json
65+
PUT /stores/_doc/3
66+
{
67+
"store_name": "City Organics",
68+
"opening_date": "2021-04-20",
69+
"coordinates": [74.02, 40.68]
70+
}
71+
```
72+
{% include copy-curl.html %}
73+
74+
## Example: Boost scores based on recency
75+
76+
The following query searches for documents with a `store_name` matching `market` and boosts recently opened stores:
77+
78+
```json
79+
GET /stores/_search
80+
{
81+
"query": {
82+
"bool": {
83+
"must": {
84+
"match": {
85+
"store_name": "market"
86+
}
87+
},
88+
"should": {
89+
"distance_feature": {
90+
"field": "opening_date",
91+
"origin": "2025-04-07",
92+
"pivot": "10d"
93+
}
94+
}
95+
}
96+
}
97+
}
98+
```
99+
{% include copy-curl.html %}
100+
101+
The response contains the matching document:
102+
103+
```json
104+
{
105+
"took": 4,
106+
"timed_out": false,
107+
"_shards": {
108+
"total": 1,
109+
"successful": 1,
110+
"skipped": 0,
111+
"failed": 0
112+
},
113+
"hits": {
114+
"total": {
115+
"value": 1,
116+
"relation": "eq"
117+
},
118+
"max_score": 1.2372394,
119+
"hits": [
120+
{
121+
"_index": "stores",
122+
"_id": "1",
123+
"_score": 1.2372394,
124+
"_source": {
125+
"store_name": "Green Market",
126+
"opening_date": "2025-03-10",
127+
"coordinates": [
128+
74,
129+
40.7
130+
]
131+
}
132+
}
133+
]
134+
}
135+
}
136+
```
137+
138+
### Example: Boost scores based on geographic proximity
139+
140+
The following query searches for documents with a `store_name` matching `market` and boosts results closer to the given origin point:
141+
142+
```json
143+
GET /stores/_search
144+
{
145+
"query": {
146+
"bool": {
147+
"must": {
148+
"match": {
149+
"store_name": "market"
150+
}
151+
},
152+
"should": {
153+
"distance_feature": {
154+
"field": "coordinates",
155+
"origin": [74.00, 40.71],
156+
"pivot": "500m"
157+
}
158+
}
159+
}
160+
}
161+
}
162+
```
163+
{% include copy-curl.html %}
164+
165+
The response contains the matching document:
166+
167+
```json
168+
{
169+
"took": 3,
170+
"timed_out": false,
171+
"_shards": {
172+
"total": 1,
173+
"successful": 1,
174+
"skipped": 0,
175+
"failed": 0
176+
},
177+
"hits": {
178+
"total": {
179+
"value": 1,
180+
"relation": "eq"
181+
},
182+
"max_score": 1.2910118,
183+
"hits": [
184+
{
185+
"_index": "stores",
186+
"_id": "1",
187+
"_score": 1.2910118,
188+
"_source": {
189+
"store_name": "Green Market",
190+
"opening_date": "2025-03-10",
191+
"coordinates": [
192+
74,
193+
40.7
194+
]
195+
}
196+
}
197+
]
198+
}
199+
}
200+
```
201+
202+
## Parameters
203+
204+
The following table lists all top-level parameters supported by `distance_feature` queries.
205+
206+
| Parameter | Required/Optional | Description |
207+
|-----------|-------------------|-------------|
208+
| `field` | Required | The name of the field used to calculate distances. Must be a `date`, `date_nanos`, or `geo_point` field with `index: true` (default) and `doc_values: true` (default). |
209+
| `origin` | Required | The point of origin used to calculate distances. Use a [date]({{site.url}}{{site.baseurl}}/field-types/supported-field-types/date/) or [date math expression]({{site.url}}{{site.baseurl}}/field-types/supported-field-types/date/#date-math) (for example, `now-1h`) for `date` fields or a [geopoint]({{site.url}}{{site.baseurl}}/field-types/supported-field-types/geo-point/) for `geo_point` fields. |
210+
| `pivot` | Required | The distance from the `origin` at which scores receive half of the `boost` value. Use a time unit (for example, `10d`) for date fields or a distance unit (for example, `1km`) for geographic fields. For more information, see [Units]({{site.url}}{{site.baseurl}}/api-reference/common-parameters/#units).|
211+
| `boost` | Optional | A multiplier for the relevance score of matching documents. Must be a non-negative float. Default is `1.0`. |
212+
213+
## How scores are calculated
214+
215+
The `distance_feature` query calculates a document's relevance score using the following formula:
216+
217+
$$ \text{score} = \text{boost} \cdot \frac {\text{pivot}} {\text{pivot} + \text{distance}} $$,
218+
219+
where $$\text{distance}$$ is the absolute difference between the `origin` and the field's value.
220+
221+
## Skipping non-competitive hits
222+
223+
Unlike other score-modifying queries like the `function_score` query, the `distance_feature` query is optimized to efficiently skip non-competitive hits when total hit tracking (`track_total_hits`) is disabled.

0 commit comments

Comments
 (0)