NEST Geo shape filter to shapes containing a point

Hi,

I'm trying to filter based on location with NEST using the docs here and post here. But I think my use case is different to those examples in two ways.

  1. I want to filter based on a point being Within a polygon/shape, but I want to filter the document associated with the shapes, not the point. As in "return only documents with a shape surrounding the point value given in the query".
  2. The documents with shapes can have a list of multiple shapes, and I want to filter out only those that have NO shape surrounding the point.

In general my setup is:

  • A PointDocument index, each PointDocument has a lat/long point field.
  • A ShapeDocument index, each ShapeDocument has a field with a list of shapes.
  • We need to query the ShapeDocuments (based on other properties). For each query we have the ID of a PointDocument the results are for, and we have to filter the ShapeDocument search results to only those that have a shape surrounding the PointDocument's point field.

Is that possible? In NEST or in general?

What I'm trying at the moment is to use Intersects with a Polygon shape but I'm not even able to index the ShapeDocuments. What I have so far:

			var shapeDocument = new ShapeDocument 
			{
                // "shapes" is a List<List<GeoCoordinate>>
				Shapes = new PolygonGeoShape(shapes)
			};

I can successfully index documents with no GeoCoordinates and they look like:

 {
                "_index": "ShapeDocumentIndex",
                "_type": "_doc",
                "_id": "someid",
                "_routing": "somerouting",
                "_source": {
                    [other fields]
                    "shapes": {
                        "type": "polygon",
                        "coordinates": []
                    }
                }

The error I get is:

Type: mapper_parsing_exception Reason: "object mapping for [shapeDocument.coordinates] tried to parse field [null] as object, but found a concrete value"

I've looked at a few posts around with that error message but I couldn't find any where the field being parsed is as "null", and I don't see why the PolygonGeoShape would be a concrete value?

Thanks very much for your help.

I never figured out what that error message meant, but some of this is working now

  1. Filtering the document with the shapes was using the "Contains" relation, not "Within".
  2. I haven't tried handling multiple shapes yet.

Changes this needed:

Mapping the geoshape property when creating the index

var result = await client.Indices.CreateAsync(indexDefinition.Name,
				x => x
					.Settings(settings => settings
						// etc, all the settings here...
					.Map<ShapeDocument>(doc => doc
						.Properties(it => it.GeoShape(g => g.Name("shapes")))
						.AutoMap()));

Indexing the shape

            // assigned elsewhere
            IReadOnlyCollection<List<NetTopologySuite.Geometries.Coordinate>> shapes; 
            var doc = new ShapeDocument
			{
				Id = someId,
				Shapes = new PolygonGeoShape(
					shapes.Select(s => s.Select(point => new Nest.GeoCoordinate(point.Y, 
                                        point.X))))
			};

            var descriptor = new BulkDescriptor();
    		descriptor.Index<DocumentBase>(
						o => o.Document(doc)
							.Id(doc.Id)
							.Index(index))
					.Refresh(Refresh.True);
            var response = await _elasticClient.BulkAsync(descriptor);

Making a filter to query with

            NotTopologySuite.Geometries.Point point = // get from the database
			QueryContainer pointWithinShapes = new GeoShapeQuery
			{
				Field = Field<ShapeDocument>(it => it.Shapes),
				Shape = new PointGeoShape(point.Y, point.X),
				Relation = GeoShapeRelation.Contains
			};

            // if the doc has no shapes, it doesn't need to be filtered out
			QueryContainer documentHasNoShapes = new BoolQuery
			{
				MustNot = new QueryContainer[]
				{
					new ExistsQuery
					{
						Field = Field<ShapeDocument>(it => it.Shapes)
					}
				}
			};

           // say that either match is ok but neither should affect the score
			QueryContainer shouldFilter = new BoolQuery
			{
				Should = new[] { pointWithinShapes , documentHasNoShapes },
				MinimumShouldMatch = 1
             };
		}