简体   繁体   中英

Elasticsearch geo query with aggregation

I have an elasticsearch index containing user locations. I need to perform aggregate query with geo bounding box using geohash grid, and for buckets that have documents count less than some value, i need to return all documents.

How can i do this?

Since you have not given any relevant information about the index which you have created and the user locations.

I am considering the below data:

index Def

{
  "mappings": {
    "properties": {
      "location": {
        "type": "geo_point"
      }
    }
  }
}   

Index Sample Doc

POST _bulk

{"index":{"_id":1}}
{"location":"52.37408,4.912350","name":"The golden dragon"}
{"index":{"_id":2}}
{"location":"52.369219,4.901618","name":"Burger King"}
{"index":{"_id":3}}
{"location":"52.371667,4.914722","name":"Wendys"}
{"index":{"_id":4}}
{"location":"51.222900,4.405200","name":"Taco Bell"}
{"index":{"_id":5}}
{"location":"48.861111,2.336389","name":"McDonalds"}
{"index":{"_id":6}}
{"location":"48.860000,2.327000","name":"KFC"}

According to your question:

When requesting detailed buckets a filter like geo_bounding_box should be applied to narrow the subject area

To know more about this, you can refer to this official ES doc

  • Now, in order to filter data based on doc_count with aggregations, we can use bucket_selector pipeline aggregation.

From documentation

Pipeline aggregations work on the outputs produced from other aggregations rather than from document sets, adding information to the output tree.

So, the amount of work that need to be done to calculate doc_count will be the same.

Query

    {
  "aggs": {
    "location": {
      "filter": {
        "geo_bounding_box": {
          "location": {
            "top_left": {
              "lat": 52.5225,
              "lon": 4.5552
            },
            "bottom_right": {
              "lat": 52.2291,
              "lon": 5.2322
            }
          }
        }
      },
      "aggs": {
        "around_amsterdam": {
          "geohash_grid": {
            "field": "location",
            "precision": 8
          },
          "aggs": {
            "the_filter": {
              "bucket_selector": {
                "buckets_path": {
                  "the_doc_count": "_count"
                },
                "script": "params.the_doc_count < 2"
              }
            }
          }
        }
      }
    }
  }
}

Search Result

"hits": {
    "total": {
      "value": 6,
      "relation": "eq"
    },
    "max_score": 1.0,
    "hits": [
      {
        "_index": "restaurant",
        "_type": "_doc",
        "_id": "1",
        "_score": 1.0,
        "_source": {
          "location": "52.37408,4.912350",
          "name": "The golden dragon"
        }
      },
      {
        "_index": "restaurant",
        "_type": "_doc",
        "_id": "2",
        "_score": 1.0,
        "_source": {
          "location": "52.369219,4.901618",
          "name": "Burger King"
        }
      },
      {
        "_index": "restaurant",
        "_type": "_doc",
        "_id": "3",
        "_score": 1.0,
        "_source": {
          "location": "52.371667,4.914722",
          "name": "Wendys"
        }
      },
      {
        "_index": "restaurant",
        "_type": "_doc",
        "_id": "4",
        "_score": 1.0,
        "_source": {
          "location": "51.222900,4.405200",
          "name": "Taco Bell"
        }
      },
      {
        "_index": "restaurant",
        "_type": "_doc",
        "_id": "5",
        "_score": 1.0,
        "_source": {
          "location": "48.861111,2.336389",
          "name": "McDonalds"
        }
      },
      {
        "_index": "restaurant",
        "_type": "_doc",
        "_id": "6",
        "_score": 1.0,
        "_source": {
          "location": "48.860000,2.327000",
          "name": "KFC"
        }
      }
    ]
  },
  "aggregations": {
    "location": {
      "doc_count": 3,
      "around_amsterdam": {
        "buckets": [
          {
            "key": "u173zy3j",
            "doc_count": 1
          },
          {
            "key": "u173zvfz",
            "doc_count": 1
          },
          {
            "key": "u173zt90",
            "doc_count": 1
          }
        ]
      }
    }
  }
}

It will filter out all the documents, whose count is less than 2 based on "params.the_doc_count < 2"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM