30

mongo 2.6

I have some amount of stored polygons. And I have a point. I what to know if this point fits any of stored polygons

document example

{ ..., "polygons" : [ [ 17.60083012593064, 78.18557739257812 ], [ 17.16834652544664, 78.19381713867188 ], [ 17.17490690610013, 78.739013671875 ], [ 17.613919673106714, 78.73489379882812 ] ], ... }

There is nearly the same question already Mongodb : Check if a point is inside a stored polygon. But it is not working for me - this query has to give at least one result(the one in example) - but it does not.

db.areas.find( { polygons : { $geoIntersects : { $geometry : {type:"Point",coordinates:[17.3734, 78.4738]} } } } )

Actually if I chose a point on a border of any polygon - it does.

$geoWithin method has to do the work as mondodb documentation says.

but any of these queries do not work

db.areas.find( { polygons : { $geoWithin : { $geometry : {type:"Point",coordinates:[17.3734, 78.4738]} } } } ) - not supported with provided geometry

db.tradeareas.find( { polygons : { $geoWithin : { $geometry : {type:"Polygon",coordinates: inside_polygon} } } } ) - BadValue bad geo query

It seems I miss something but cant understand what and where.

I would be grateful for help.

Ossir
  • 3,109
  • 1
  • 34
  • 52
user3806072
  • 303
  • 1
  • 3
  • 4

3 Answers3

50

It seems to be to do with the order. If you are using $geoWithin and you are trying to find points inside a polygon, the thing that is within is the field you are searching on. However, $geoIntersects works in either direction, so you can search for points inside polygons, or polygons containing points, eg:

db.geom.insert({
  "polygons": {
    "type":"Polygon",
    "coordinates": [[
      [ 17.60083012593064, 78.18557739257812],
      [ 17.16834652544664, 78.19381713867188],
      [ 17.17490690610013, 78.739013671875],
      [ 17.613919673106714, 78.73489379882812],
      [ 17.60083012593064, 78.18557739257812]
    ]]
  }
});

db.geom.find({
  polygons: {
    $geoIntersects: {
      $geometry: {
        "type": "Point",
        "coordinates": [17.3734, 78.4738]
      }
    }
  }
});

Also, note that, you need to repeat the first point of the polygon at the end. If you remove the final pair, you will get a $err:

Can't canonicalize query: BadValue bad geo query" error.

It seems that MongoDB allows you to insert invalid geometries and only complains when you try and add a 2dsphere index or do an intersects/within/near query, which, I suppose is reasonable, as GeoJSON can be valid JSON without being a valid geometry.

alexmac
  • 19,087
  • 7
  • 58
  • 69
John Powell
  • 12,253
  • 6
  • 59
  • 67
  • Thank you for reply. I made such tests as you suggest - it does work correctly - just like in mongo documentation example. But I dont have polygons. I have just a point as parameter. To get a polygon I need to make a request to DB. So with a million records - i need a 2 million requests to find all polygons that contains my point – user3806072 Jul 08 '14 at 09:37
  • @user3806072. I have updated my answer, it works as expected now, it will find all polygons that contain a point. – John Powell Jul 08 '14 at 11:02
  • thank you very much - it does work. As you mentioned - The mistake was in incorrect GEOJSON structure of saved polygon. – user3806072 Jul 08 '14 at 11:27
  • @user3806072 I am having the same issue you were having. I do think it's the GEOJSON structure of the saved polygon. What did you change the structure to? What does your schema look like? Thanks much! – rmg.n3t Oct 29 '15 at 16:34
  • What do you mean by "It seems to be to do with the order"? – Chris Jan 26 '17 at 21:14
  • Would it be possible to achieve the same thing if we have a multiple of polygons and points within our database? Could we have point-in-polygon analysis in MongoDB implicity? – banbar Dec 14 '17 at 19:29
  • 1
    @banbar. Sorry, I don't really work with MongoDB any more. I am sure you can achieve that, but I think you might want to ask that as a separate question. – John Powell Dec 15 '17 at 08:44
1

Thanks for John Powell here is C# driver version of the same query.

 var geometry = new BsonDocument
                            {
                                     { "type", "Point" },
                                     { "coordinates",
                                        new BsonArray(new double[]{ Longitude,
                                        Latitude} ) }
                            };
                    var geometryOperator = new BsonDocument { { "$geometry", geometry } };
                    var geoIntersectsOperator = new BsonDocument { { "$geoIntersects", geometryOperator } };

                    var findField = new BsonDocument { { "geometry", geoIntersectsOperator } };


                    var results = MyCollection.Find(findField).ToList();
HaBo
  • 13,999
  • 36
  • 114
  • 206
0

In Java it Can be done this way

@Autowired
private MongoOperations mongoOpertions;
    
public void pointIntersect(GeoJsonPoint gp){
    Query query = new Query();
    query.addCriteria(Criteria.where("geometry").intersects(gp));
    List<ResultDtoType> result = mongoOpertions.find(query, ResultDtoType.class);
    //perform any action with result 
}
Alex Reinking
  • 16,724
  • 5
  • 52
  • 86