ElasticSearch - Return 字段值的唯一结果
ElasticSearch - Return unique result by field values
我有 3 个 "places",每个都有一个类型和一个位置:
PUT places
{
"mappings": {
"test": {
"properties": {
"type": { "type": "keyword" },
"location": { "type": "geo_point" }
}
}
}
}
POST places/test
{
"type" : "A",
"location": {
"lat": 1.378446,
"lon": 103.763427
}
}
POST places/test
{
"type" : "B",
"location": {
"lat": 1.478446,
"lon": 104.763427
}
}
POST places/test
{
"type" : "A",
"location": {
"lat": 1.278446,
"lon": 102.763427
}
}
我只想检索每个 "type" 的一个位置:离随机位置最近的位置可以说 "lat":1.178446,"lon":101.763427
在我的示例中,结果答案应该正好由 2 个元素组成(一个用于 "type: A",一个用于 "type: B")。
我也希望避免使用 "aggregations",因为我需要每个地方的 _source。
任何帮助都会很棒。
如果没有聚合,这样的操作似乎不可能执行一个查询。
这可以通过 top-hits-aggregation.
来实现
下面已经用 elasticsearch 6 测试过:
POST /places/_search?size=0
{
"aggs" : {
"group-by-type" : {
"terms" : { "field" : "type" },
"aggs": {
"min-distance": {
"top_hits": {
"sort": {
"_script": {
"type": "number",
"script": {
"source": "def x = doc['location'].lat; def y = doc['location'].lon; return Math.abs(x-1.178446) + Math.abs(y-101.763427)",
"lang": "painless"
},
"order": "asc"
}
},
"_source": {
"includes": [ "type", "location" ]
},
"size" : 1
}
}
}
}
}
}
注意,我计算的距离为:
|location.x - givenPoint.x| + |location.y - givenPoint.y|
这是回复:
{
"took": 2,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 3,
"max_score": 0.0,
"hits": []
},
"aggregations": {
"group-by-type": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [{
"key": "A",
"doc_count": 2,
"min-distance": {
"hits": {
"total": 2,
"max_score": null,
"hits": [{
"_index": "places",
"_type": "test",
"_id": "3",
"_score": null,
"_source": {
"location": {
"lon": 102.763427,
"lat": 1.278446
},
"type": "A"
},
"sort": [1.1000006934661934]
}]
}
}
}, {
"key": "B",
"doc_count": 1,
"min-distance": {
"hits": {
"total": 1,
"max_score": null,
"hits": [{
"_index": "places",
"_type": "test",
"_id": "2",
"_score": null,
"_source": {
"location": {
"lon": 104.763427,
"lat": 1.478446
},
"type": "B"
},
"sort": [3.3000007411499093]
}]
}
}
}]
}
}
}
我有 3 个 "places",每个都有一个类型和一个位置:
PUT places
{
"mappings": {
"test": {
"properties": {
"type": { "type": "keyword" },
"location": { "type": "geo_point" }
}
}
}
}
POST places/test
{
"type" : "A",
"location": {
"lat": 1.378446,
"lon": 103.763427
}
}
POST places/test
{
"type" : "B",
"location": {
"lat": 1.478446,
"lon": 104.763427
}
}
POST places/test
{
"type" : "A",
"location": {
"lat": 1.278446,
"lon": 102.763427
}
}
我只想检索每个 "type" 的一个位置:离随机位置最近的位置可以说 "lat":1.178446,"lon":101.763427
在我的示例中,结果答案应该正好由 2 个元素组成(一个用于 "type: A",一个用于 "type: B")。
我也希望避免使用 "aggregations",因为我需要每个地方的 _source。
任何帮助都会很棒。
如果没有聚合,这样的操作似乎不可能执行一个查询。 这可以通过 top-hits-aggregation.
来实现下面已经用 elasticsearch 6 测试过:
POST /places/_search?size=0
{
"aggs" : {
"group-by-type" : {
"terms" : { "field" : "type" },
"aggs": {
"min-distance": {
"top_hits": {
"sort": {
"_script": {
"type": "number",
"script": {
"source": "def x = doc['location'].lat; def y = doc['location'].lon; return Math.abs(x-1.178446) + Math.abs(y-101.763427)",
"lang": "painless"
},
"order": "asc"
}
},
"_source": {
"includes": [ "type", "location" ]
},
"size" : 1
}
}
}
}
}
}
注意,我计算的距离为:
|location.x - givenPoint.x| + |location.y - givenPoint.y|
这是回复:
{
"took": 2,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 3,
"max_score": 0.0,
"hits": []
},
"aggregations": {
"group-by-type": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [{
"key": "A",
"doc_count": 2,
"min-distance": {
"hits": {
"total": 2,
"max_score": null,
"hits": [{
"_index": "places",
"_type": "test",
"_id": "3",
"_score": null,
"_source": {
"location": {
"lon": 102.763427,
"lat": 1.278446
},
"type": "A"
},
"sort": [1.1000006934661934]
}]
}
}
}, {
"key": "B",
"doc_count": 1,
"min-distance": {
"hits": {
"total": 1,
"max_score": null,
"hits": [{
"_index": "places",
"_type": "test",
"_id": "2",
"_score": null,
"_source": {
"location": {
"lon": 104.763427,
"lat": 1.478446
},
"type": "B"
},
"sort": [3.3000007411499093]
}]
}
}
}]
}
}
}