Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

$geoNear (aggregate pipeline) not returning correct documents

I am not getting the correct results returned when using $geoNear in the aggregate pipeline. The same query using a typical find() query (using $near) does in fact return the right results.

BUT, when removing the equality condition (on schedule.key), both queries return the correct data.

$geoNear using aggregate pipeline:

db.place.aggregate(
[
    { 
        $geoNear: { 
            spherical: true,
            near: { type: "Point", coordinates: [ 18.416145, -33.911973 ] },
            distanceField: "dist"
        }
    },
    { 
        $match: { 
            "schedule.key": { "$eq": "vo4lRN_Az0uwOkgBzOERyw" } 
        } 
    }
])

$near find query:

db.place.find(
    { 
        "point" : { 
            $near: { 
                type: "Point", 
                coordinates: [ 18.416145,-33.911973 ] 
            } 
        }, 
        "schedule.key" : { 
            $eq : "vo4lRN_Az0uwOkgBzOERyw" 
        }
    })

A document in this collection looks something like this:

{
    "_id" : UUID("da6ccbb1-3c7a-45d7-bc36-a5e6007cd919"),
    "schedule" : {
        "_id" : UUID("587de5b7-a744-4b28-baa8-e6efb5f7f921"),
        "key" : "vo4lRN_Az0uwOkgBzOERyw"
    },
    "point" : {
        "type" : "Point",
        "coordinates" : [ 
            18.425102, 
            -33.922153
        ]
    },
    "name" : "Cape Town"
}

I have created the appropriate index on the point field:

db.place.ensureIndex( { "point" : "2dsphere" } );
like image 851
Dave New Avatar asked Oct 19 '22 11:10

Dave New


1 Answers

It's not the "same" query at all. There is a distinct difference in using a separate $match stage, since the "filtering" is only done "after" the "nearest resuts" are found. This means that you potentially return "less" results since the criteria is not issued in combination.

That's why there is a "query" option in $geoNear:

db.place.aggregate(
[
    { 
        $geoNear: { 
            spherical: true,
            near: { type: "Point", coordinates: [ 18.416145, -33.911973 ] },
            distanceField: "dist",
            query: {
                "schedule.key": { "$eq": "vo4lRN_Az0uwOkgBzOERyw" } 
            }
        }
    }
])

Now that's the same query. Or it would be exactly the same if you used $nearSphere. Since $near does not account for the curvature of the earth in distance calcuations. $nearSphere and $geoNear does.

But the main point is combining with the "query" option, since that's the only way you truly get both criteria considered in the initial search.

like image 176
Neil Lunn Avatar answered Oct 31 '22 11:10

Neil Lunn