我正在使用Elasticsearch在查找其他用户时存储用户位置及其距离偏好。它存储在location
geo_point和distance
整数中。
例如,索引包含以下文档:
当位于[0,0]的Carlos在100米范围内搜索时,我需要我的查询返回Alice,但不是 Bob(因为Bob只需要50米以内的用户,而Carlos距离100米)。
换句话说,我想返回所有文档D
,以便D.reach
包含Carlos.location
而Carlos.reach
包含D.location
。
据我所知,唯一的方法是将距离与脚本进行比较,如下所示:
{
"filter": {
"script": {
"script": "min(doc['distance'].value, distance) >= doc['location'].arcDistance(lat, lon)",
"params": {
"distance": 100,
"lat": 0,
"lon": 0
}
}
}
}
但是,如果可能的话我会rather avoid scripting。有没有其他方法可以实现这一目标?
答案 0 :(得分:0)
值得调查的另一种方法是使用geo_shape
circle
。因此,除了(或除了)存储location
和distance
的离散值之外,您还可以将这两个值的组合存储为表示用户的reach
的圆圈。在您的映射中,它看起来像这样:
{
"properties": {
"reach": {
"type": "geo_shape",
"tree": "quadtree",
"precision": "10cm"
}
}
}
然后,当您为文档编制索引时,您可以像这样指定reach
圈:
{
"name": "Alice",
"reach" : {
"type" : "circle",
"coordinates" : [0.0, 100.0], <---- Alice's current location field
"radius" : "100m" <---- Alice's current distance field
}
}
{
"name": "Bob",
"reach" : {
"type" : "circle",
"coordinates" : [100.0, 0.0], <---- Bob's current location field
"radius" : "50m" <---- Bob's current distance field
}
}
此时,您的所有用户都会geo_shape
与他们相关联,代表他们的覆盖面。现在,您可以释放ES地理查询和过滤器的强大功能,以便查找交叉点或您拥有的内容,例如使用geo_shape
filter。我们的想法是过滤另一个geo_shape
,代表搜索其他用户的用户的覆盖面(例如上面的Carlos)
{
"query":{
"filtered": {
"filter": {
"geo_shape": {
"location": {
"shape": {
"type": "circle",
"coordinates" : [0.0, 0.0] <--- Carlos location
"radius": "100m" <--- Carlos reach
}
}
}
}
}
}
}
上述查询将查找其覆盖范围与Carlos相交的所有文档(即用户)。过滤器中指定的到达范围。试一试。
答案 1 :(得分:0)
由于Val的答案指向了正确的方向,我使用了以下解决方案。
文档看起来像这样,包含用户&#39;地址为geo_point
,并以geo_shape
为目标。
{
"name": "Alice",
"location" : [1,0],
"reach" : {
"type": "shape",
"coordinates": [1,0],
"radius": 100
}
}
然后查询包含两个过滤器;一个匹配卡洛斯&#39;用户内部的位置&#39;到达,另一个用于匹配用户在卡洛斯内部的位置&#39;达到。
{
"filter": {
"and" : [
{
"geo_shape": {
"preferences.reach": {
"shape": {
"type": "Point",
"coordinates": Carlos.location
}
}
}
},
{
"geo_distance": {
"distance": Carlos.distance,
"user.location" : Carlos.location
}
}
]
}
}
这可以通过两个geo_shape
来完成,但geo_point
更高效。