Byron Voorbach
Byron Voorbach

Reputation: 4485

Elasticsearch geo_shape filter no results

I'm having issues with getting my geo_shape filter to return results when filtering on a nested location.

Suppose I have the following:

PUT test/test/_mapping
{
  "properties": {
    "name": {
      "type": "string"
    },
    "gatheringEvent": {
      "properties": {
        "siteCoordinates": {
          "type": "nested",
          "properties": {
            "point": {
              "type": "geo_shape"
            }
          }
        }
      }
    },
    "point": {
      "type": "geo_shape"
    }
  }
}

Now when I index the following document:

POST test/test/1
{
  "name": "Bird",
  "gatheringEvent.siteCoordinates.point": {
    "type": "point",
    "coordinates": [
      5,
      5
    ]
  },
  "point": {
    "type": "point",
    "coordinates": [
      5,
      5
    ]
  }
}

Executing the following query: (using geo_shape filter on non-nested location)

GET test/test/_search
{
  "query": {
    "filtered": {
      "query": {
        "match": {
          "name": "Bird"
        }
      },
      "filter": {
        "geo_shape": {
          "point": {
            "shape": {
              "type": "polygon",
              "coordinates": [
                [
                  [0 ,0 ],
                  [10 ,0],
                  [10,10],
                  [0,10 ],
                  [0 ,0 ]
                ]
              ]
            },
            "relation": "within"
          }
        }
      }
    }
  }
}

Gives me back my document as I would expect.

But when executing the geo_shape filter on the nested location:

GET test/test/_search
{
  "query": {
    "filtered": {
      "query": {
        "match": {
          "name": "Bird"
        }
      },
      "filter": {
        "nested": {
          "path": "gatheringEvent.siteCoordinates",
          "filter": {
            "geo_shape": {
              "gatheringEvent.siteCoordinates.point": {
                "shape": {
                  "type": "polygon",
                  "coordinates": [
                    [
                      [0 ,0 ],
                      [10 ,0],
                      [10,10],
                      [0,10 ],
                      [0 ,0 ]
                    ]
                  ]
                },
                "relation": "within"
              }
            }
          }
        }
      }
    }
  }
}

Yields no results..

I also removed the nested mapping because I thought that might be the issue, but as soon as the 'point' field resides inside an object type field, I get no results..

Any thoughts on what I'm doing wrong here??

Thanks.

Upvotes: 1

Views: 1022

Answers (1)

Sloan Ahrens
Sloan Ahrens

Reputation: 8718

There are a couple of problems I see here:

  • It looks like you want two levels of nesting (unless that's a mistake), so you need to specify both levels in your mapping if you want to be able to use the nested filter in your query.
  • You can't use the dot syntax when indexing your document with nested structure; that syntax is only for querying. If you look at your mapping before and after you index the document, you will see that a top-level property called "gatheringEvent.siteCoordinates.point" gets added when you index the document, which presumably isn't what you wanted.

There are a few different ways you could proceed. Here's how I was able to get it to work. First I modified your mapping to include two levels of nesting, and created an index as follows:

DELETE /test_index

PUT /test_index
{
   "settings": {
      "number_of_shards": 1,
      "number_of_replicas": 0
   }
}

PUT /test_index/doc/_mapping
{
   "properties": {
      "name": {
         "type": "string"
      },
      "gatheringEvent": {
         "type": "nested",
         "properties": {
            "siteCoordinates": {
               "type": "nested",
               "properties": {
                  "point": {
                     "type": "geo_shape"
                  }
               }
            }
         }
      },
      "point": {
         "type": "geo_shape"
      }
   }
}

Then I indexed your document with the proper structure for two levels of nesting:

POST /test_index/doc/1
{
   "name": "Bird",
   "gatheringEvent": [
      {
         "siteCoordinates": [
            {
               "point": {
                  "type": "point",
                  "coordinates": [5, 5]
               }
            }
         ]
      }
   ],
   "point": {
      "type": "point",
      "coordinates": [5, 5]
   }
}

I also added a second document outside your bounding box, as a sanity check:

POST /test_index/doc/2
{
   "name": "Bird",
   "gatheringEvent": [
      {
         "siteCoordinates": [
            {
               "point": {
                  "type": "point",
                  "coordinates": [6, 11]
               }
            }
         ]
      }
   ],
   "point": {
      "type": "point",
      "coordinates": [6, 11]
   }
}

Now both of your queries work as expected:

POST /test_index/doc/_search
{
  "query": {
    "filtered": {
      "query": {
        "match": {
          "name": "Bird"
        }
      },
      "filter": {
        "nested": {
          "path": "gatheringEvent.siteCoordinates",
          "filter": {
            "geo_shape": {
              "gatheringEvent.siteCoordinates.point": {
                "shape": {
                  "type": "polygon",
                  "coordinates": [
                    [
                      [0, 0],
                      [10, 0],
                      [10, 10],
                      [0, 10],
                      [0, 0]
                    ]
                  ]
                },
                "relation": "within"
              }
            }
          }
        }
      }
    }
  }
}
{
   "took": 2,
   "timed_out": false,
   "_shards": {
      "total": 1,
      "successful": 1,
      "failed": 0
   },
   "hits": {
      "total": 1,
      "max_score": 1.6931472,
      "hits": [
         {
            "_index": "test_index",
            "_type": "doc",
            "_id": "1",
            "_score": 1.6931472,
            "_source": {
               "name": "Bird",
               "gatheringEvent": [
                  {
                     "siteCoordinates": [
                        {
                           "point": {
                              "type": "point",
                              "coordinates": [
                                 5,
                                 5
                              ]
                           }
                        }
                     ]
                  }
               ],
               "point": {
                  "type": "point",
                  "coordinates": [
                     5,
                     5
                  ]
               }
            }
         }
      ]
   }
} 

If you only actually wanted one level of nesting, it's even easier. I can add that code too if you want, just ask.

Here is the code I used:

http://sense.qbox.io/gist/e61259626d5f8525ee41ce7b049af25089bfb8f6

Upvotes: 3

Related Questions