Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Will a Mongo $near return documents for which any point in a MultiPoint is within range?

Tags:

mongodb

When using $near/$geoNear/$geoWithin on a MultiPoint GeoJson object, will the document be returned if any of the points is within the range, or do they all have to be in range?

like image 519
tarmes Avatar asked Nov 18 '15 15:11

tarmes


1 Answers

Case for "near"

The distance considered will always be from the "nearest" point of any GeoJSON Object stored. The same goes for Polygon, or MultiPolygon and really all GeoJSON objects that are valid for storage.

Consider this:

{
    "location": {
       "type": "MultiPoint",
       "coordinates": [
          [ -73.9580, 40.8003 ],
          [ -73.9498, 40.7968 ],
          [ -73.9737, 40.7648 ],
          [ -73.9814, 40.7681 ]
       ]
    }
}

And if we use aggregation $geoNear as a means to show us the distance from a given location:

db.geo.aggregate([
    { "$geoNear": {
        "near": {
            "type": "Point",
            "coordinates": [
               -73.97661209106445,
               40.774561857347244
            ]
        },
        "spherical": true,
        "distanceField": "distance"
    }}
])

This tels us that the distance is considered to be 824 meters.

Now if you considered each "Point" as it's own document instead in the collection, and ran the same query process:

{
        "location" : {
                "type" : "Point",
                "coordinates" : [
                        -73.9814,
                        40.7681
                ]
        },
        "distance" : 824.837276194968
}
{
        "location" : {
                "type" : "Point",
                "coordinates" : [
                        -73.9737,
                        40.7648
                ]
        },
        "distance" : 1114.0666715946495
}
{
        "location" : {
                "type" : "Point",
                "coordinates" : [
                        -73.958,
                        40.8003
                ]
        },
        "distance" : 3266.4720692258156
}
{
        "location" : {
                "type" : "Point",
                "coordinates" : [
                        -73.9498,
                        40.7968
                ]
        },
        "distance" : 3351.9091229713567
}

Then you see the different distances of each point from the point of origin is the query, where in the former case only the "nearest" was actually considered for the whole object.

So there is the proof, that the distance considered with $near/$geoNear or is always only the nearest point to the origin used in the query.

Case for $geoWithin

The $geoWithin operation is however different. Consider the orginial "MultiPoint" document and then this query:

db.geo.find({
    "location": {
        "$geoWithin": {
            "$geometry": {
                "type": "Polygon",
                "coordinates": [
                  [
                    [
                      -73.98382186889648,
                      40.75961056635002
                    ],
                    [
                      -74.00030136108398,
                      40.782751138401245
                    ],
                    [
                      -73.97317886352539,
                      40.78950978441435
                    ],
                    [
                      -73.95910263061523,
                      40.7720918760227
                    ],
                    [
                      -73.98382186889648,
                      40.75961056635002
                    ]
                  ]
                ]
            }
        }
    }
})

This will not return any result, and it will not because "not all" Point components of the Object lie within the bounds of tge Polygon used in the query. But if you considered each point as a single document:

{
        "_id" : ObjectId("564d5efd9f28c6e0feabcef8"),
        "location" : {
                "type" : "Point",
                "coordinates" : [
                        -73.9737,
                        40.7648
                ]
        }
}
{
        "_id" : ObjectId("564d5efd9f28c6e0feabcef9"),
        "location" : {
                "type" : "Point",
                "coordinates" : [
                        -73.9814,
                        40.7681
                ]
        }
}

Then two of the points would be seen to be inside the Polygon. But since these are not stored as individual documents but as part of a "MutiPoint", then unless all parts of that Object are contained within the shape, then the result is false and the document is not returned.

The same is true here for all GeoJSON Objects that essentially contain a collection of "Point" in some representation.

like image 187
Blakes Seven Avatar answered Nov 15 '22 20:11

Blakes Seven