Elasticsearch Geo Distance查询

时间:2015-02-23 15:17:02

标签: elasticsearch

我在geo_point

的正确映射中找到了与其相关的纬度和经度的地方列表

我还有一个查询成功返回基于地理距离的结果,如下所示:

{
  "filter": {
    "geo_distance": {
      "distance": "30mi",
      "companies.locations": {
        "lat": "51.8801595",
        "lon": "0.577141"
      }
    }
  },
  "sort": {
    "_geo_distance": {
      "companies.locations": {
        "lat": "51.8801595",
        "lon": "0.577141"
      },
      "order": "asc",
      "unit": "mi",
      "mode": "min"
    }
  },
  "from": 0,
  "size": 500
}

因此,目前返回的结果在提供的纬度和经度的30英里范围内。这很好。

我正在努力迈出下一步,我希望有人能指出我正确的方向。

每个地方都有一个名为distance的字段,它是一个整数。这是一个地方愿意前往客户的最大距离。因此,如果距离为20(英里),但其纬度和经度计算超过20英里,则应将其排除在结果之外。

结果如下:

{
  "took": 1,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 1,
    "max_score": null,
    "hits": [
      {
        "_index": "test",
        "_type": "places",
        "_id": "AUtvK2OILrMWSKLclj9Z",
        "_score": null,
        "_source": {
          "id": "1",
          "name": "Chubby Company",
          "summary": "",
          "content": "",
          "locations": [
            {
              "lat": 51.8200763,
              "lon": 0.5264076
            }
          ],
          "address": [
            {
              "addr1": "xxxx",
              "addr2": "",
              "town": "MyTown",
              "county": "Essex",
              "postcode": "XX1 2XX",
              "tel1": "01111 111111",
              "tel2": "",
              "email": null
            }
          ],
          "website": "",
          "media": {
            "logo": "",
            "image": "",
            "video": ""
          },
          "product_ids": [
            "1",
            "3",
            "2"
          ],
          "distance": "20"
        },
        "sort": [
          0.031774582056958885
        ]
      }
    ]
  }
}

sort对象是以英里为单位的距离,因此上面的结果距客户端0.03英里。

我正在尝试利用这个来检查记录,使用结果将其从结果中排除,但这就是我摔倒的地方。

我尝试了不同的组合:

"script": {
  "script": "doc['distance'].value < doc['sort'].value"
}
与查询结合的

如下所示:

{
  "filter": {
    "geo_distance": {
      "distance": "30mi",
      "companies.locations": {
        "lat": "51.8801595",
        "lon": "0.577141"
      }
    }
  },
  "sort": {
    "_geo_distance": {
      "companies.locations": {
        "lat": "51.8801595",
        "lon": "0.577141"
      },
      "order": "asc",
      "unit": "mi",
      "mode": "min"
    }
  },
  "filtered": {
    "filter": {
      "script": {
        "script": "doc['distance'].value < doc['sort'].value"
      }
    }
  },
  "from": 0,
  "size": 500
}

但我收到错误:

  

SearchPhaseExecutionException [无法执行阶段[查询],全部   碎片失败...解析失败[没有解析元素[filtered]

任何建议都会很棒。

更新

尝试这个也失败了:

{
  "filter": {
    "geo_distance": {
      "distance": "30mi",
      "companies.locations": {
        "lat": "51.8801595",
        "lon": "0.577141"
      }
    },
    "script": {
      "script": "_source.distance < sort.value"
    }
  },
  "sort": {
    "_geo_distance": {
      "companies.locations": {
        "lat": "51.8801595",
        "lon": "0.577141"
      },
      "order": "asc",
      "unit": "mi",
      "mode": "min"
    }
  },
  "from": 0,
  "size": 500
}

  

嵌套:ElasticsearchParseException [预期的字段名称,但得到了START_OBJECT \“script \”]; }]”, “状态”:400}

1 个答案:

答案 0 :(得分:3)

我有一个类似的问题,我希望每个记录都有一个条件距离,这个值存储在数据中(searchRadius对我来说)。我最终在Java中使用了AndFilterBuilder和ScriptFilterBuilder类,因此AndFilterBuilder有一个GeoDistanceFilterBuilder和ScriptFilterBuilder的数组。

{
    "from": 0,
    "size": 20,
    "query": {
        "filtered": {
            "query": {
                "match_all": {}
            },
            "filter": {
                "and": {
                    "filters": [
                        {
                            "geo_distance": {
                                "location": [
                                    -104.99230194091797,
                                    39.74000930786133
                                ],
                                "distance": "3000mi"
                            }
                        },
                        {
                            "script": {
                                "script": "doc['location'].arcDistanceInMiles(39.74000930786133, -104.99230194091797) < doc['searchRadius'].value"
                            }
                        }
                    ]
                }
            }
        }
    },
    "fields": "_source",
    "script_fields": {
        "distance": {
            "script": "doc['location'].distance(39.74000930786133, -104.99230194091797)"
        }
    },
    "sort": [
        {
            "_geo_distance": {
                "location": [
                    -104.99230194091797,
                    39.74000930786133
                ],
                "unit": "mi"
            }
        }
    ]
}