How to find polygons that contain a given point in Elasticsearch

I need to build a query on a database with around 50k terrain polygons (stored as geo_shape polygons on ES) where I give a point and it returns every polygon that contains this point.

I tried to create it, but getting incorrect result.

// Code

  1. Create Index
{
    "mappings": {
        "TYPE_NAME": {
            "properties": {
                "location": {
                    "type": "geo_shape"
                }
            }
        }
    }
}
  1. Insert document:
{
    "location": {
        "type": "polygon",
        "coordinates": [
            [
                [
                    88.357934264,
                    22.55818208
                ],
                [
                    88.365144042,
                    22.556745416
                ],
                [
                    88.363384513,
                    22.551920096
                ],
                [
                    88.360412625,
                    22.552474967
                ],
                [
                    88.360788135,
                    22.553614427
                ],
                [
                    88.35667899,
                    22.55359461
                ],
                [
                    88.357934264,
                    22.55818208
                ]
            ]
        ]
    }
}
  1. Search for all polygons that contain the point:
{
    "query": {
        "geo_shape": {
            "location": {
                "shape": {
                    "type": "point",
                    "coordinates": [88.360, 22.555]
                },
                "relation": "within"
            }
        }
    }
}

Result:

{
    "took": 1,
    "timed_out": false,
    "_shards": {
        "total": 5,
        "successful": 5,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": 0,
        "max_score": null,
        "hits": []
    }
}

Please let me know if I am missing out something as it is returning WRONG result.

Hi @Pranav_Kapur

Try this

GET discuss-geo/_search
{
  "query": {
    "geo_shape": {
      "location": {
        "shape": {
          "type": "point",
          "coordinates": [
            88.36,
            22.555
          ]
        },
        "relation": "contains"
      }
    }
  }
}

Read the spatial relationship a little closer

  • WITHIN - Return all documents whose geo_shape or geo_point field is within the query geometry. Line geometries are not supported.

When you said within I believe you were asking for your shape that was within the point :slight_smile: which is not correct for Point in Polygon

You want to use contains

  • CONTAINS - Return all documents whose geo_shape or geo_point field contains the query geometry.

And this is the result

{
  "took": 2,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 1,
      "relation": "eq"
    },
    "max_score": 0,
    "hits": [
      {
        "_index": "discuss-geo",
        "_id": "Zwy9zIoBC8AxxyqEFesV",
        "_score": 0,
        "_source": {
          "location": {
            "type": "polygon",
            "coordinates": [
              [
                [
                  88.357934264,
                  22.55818208
                ],
                [
                  88.365144042,
                  22.556745416
                ],
                [
                  88.363384513,
                  22.551920096
                ],
                [
                  88.360412625,
                  22.552474967
                ],
                [
                  88.360788135,
                  22.553614427
                ],
                [
                  88.35667899,
                  22.55359461
                ],
                [
                  88.357934264,
                  22.55818208
                ]
              ]
            ]
          }
        }
      }
    ]
  }
}

Hi @stephenb

I tried using relation: "contains",

{
  "query": {
    "geo_shape": {
      "location": {
        "shape": {
          "type": "point",
          "coordinates": [
            88.36,
            22.555
          ]
        },
        "relation": "contains"
      }
    }
  }
}

but I am getting the following error:

{
    "error": {
        "root_cause": [
            {
                "type": "query_shard_exception",
                "reason": "CONTAINS query relation not supported for Field [location]",
                "index_uuid": "a4PebYDsRHiXSJmIU6U5eA",
                "index": "test"
            }
        ],
        "type": "search_phase_execution_exception",
        "reason": "all shards failed",
        "phase": "query",
        "grouped": true,
        "failed_shards": [
            {
                "shard": 0,
                "index": "test",
                "node": "vchTHFfmRVGTtVELK5UquQ",
                "reason": {
                    "type": "query_shard_exception",
                    "reason": "CONTAINS query relation not supported for Field [location]",
                    "index_uuid": "a4PebYDsRHiXSJmIU6U5eA",
                    "index": "test"
                }
            }
        ]
    },
    "status": 400
}

@Pranav_Kapur Forgot .. Welcome to the community

My entire code is below, try mine and see what you get.

What version are you on?

PUT discuss-geo
{
  "mappings": {
    "properties": {
      "location": {
        "type": "geo_shape"
      }
    }
  }
}

POST discuss-geo/_doc
{
    "location": {
        "type": "polygon",
        "coordinates": [
            [
                [
                    88.357934264,
                    22.55818208
                ],
                [
                    88.365144042,
                    22.556745416
                ],
                [
                    88.363384513,
                    22.551920096
                ],
                [
                    88.360412625,
                    22.552474967
                ],
                [
                    88.360788135,
                    22.553614427
                ],
                [
                    88.35667899,
                    22.55359461
                ],
                [
                    88.357934264,
                    22.55818208
                ]
            ]
        ]
    }
}


GET discuss-geo/_search
{
  "query": {
    "geo_shape": {
      "location": {
        "shape": {
          "type": "point",
          "coordinates": [
            88.36,
            22.555
          ]
        },
        "relation": "contains"
      }
    }
  }
}


# Result

{
  "took": 2,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 1,
      "relation": "eq"
    },
    "max_score": 0,
    "hits": [
      {
        "_index": "discuss-geo",
        "_id": "Zwy9zIoBC8AxxyqEFesV",
        "_score": 0,
        "_source": {
          "location": {
            "type": "polygon",
            "coordinates": [
              [
                [
                  88.357934264,
                  22.55818208
                ],
                [
                  88.365144042,
                  22.556745416
                ],
                [
                  88.363384513,
                  22.551920096
                ],
                [
                  88.360412625,
                  22.552474967
                ],
                [
                  88.360788135,
                  22.553614427
                ],
                [
                  88.35667899,
                  22.55359461
                ],
                [
                  88.357934264,
                  22.55818208
                ]
              ]
            ]
          }
        }
      }
    ]
  }
}

You code here do not look correct

{
    "mappings": {
        "TYPE_NAME": { <!---- What is this?
            "properties": {
                "location": {
                    "type": "geo_shape"
                }
            }
        }
    }
}

Hi @stephenb

Elastic search version is 6.8.6

I tried creating index with the code that you shared:

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

but, I get the following error:

{
    "error": {
        "root_cause": [
            {
                "type": "mapper_parsing_exception",
                "reason": "Root mapping definition has unsupported parameters:  [location : {type=geo_shape}]"
            }
        ],
        "type": "mapper_parsing_exception",
        "reason": "Failed to parse mapping [properties]: Root mapping definition has unsupported parameters:  [location : {type=geo_shape}]",
        "caused_by": {
            "type": "mapper_parsing_exception",
            "reason": "Root mapping definition has unsupported parameters:  [location : {type=geo_shape}]"
        }
    },
    "status": 400
}

I googled it, and found some link where, the below code was mentioned. I tried it and was able to create the index:

{
    "mappings": {
        "TYPE_NAME": {
            "properties": {
                "location": {
                    "type": "geo_shape"
                }
            }
        }
    }
}

In the link, TYPE_NAME was mentioned as "type_Mapping".

Hi @Pranav_Kapur you are on an INCREDIBILY old / out of date version of elasticsearch, many years out of date.

There have been massive improvements in the spatial capabilities

I do not even have a cluster to test on...

The reason I do recognize the TYPE_NAME as that is no longer valid on modern version... that was taken out in 7.x

You need to read the 6.8 docs super close all the spatial strategy stuff and types etc..etc..

IMPORTANT NOTES

The following features are not yet supported with the new indexing approach:

  • geo_shape query with MultiPoint geometry types - Elasticsearch currently prevents searching geo_shape fields with a MultiPoint geometry type to avoid a brute force linear search over each individual point. For now, if this is absolutely needed, this can be achieved using a bool query with each individual point.
  • CONTAINS relation query - when using the new default vector indexing strategy, geo_shape queries with relation defined as contains are not yet supported. If this query relation is an absolute necessity, it is recommended to set strategy to quadtree and use the deprecated PrefixTree strategy indexing approach.

You best approach would be to get on a new version ASAP.

Don't google :slight_smile: read our docs in detail

Removal of Mapping Type

time being replace TYPE_NAME with _doc

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.