combine geoNear query with another query for a value

℡╲_俬逩灬. 提交于 2019-12-04 15:12:30

As long as your MongoDB server is recent enough, being a version of 2.6 or greater then this functionality has actually been moved to the general query engine. The mongoose method here wraps the .runCommand() form which is considered deprecated for all future releases, so it is just a matter of placing a standard query with additional operators.

GeoLocation.find({
    "$nearSphere": {
        "$geometry": {
            "type": "Point",
            "coordinates": [parseFloat(req.params.lng), parseFloat(req.params.lat)] 
        },
        "$maxDistance": distanceInMeters
    },
    "loc.type": "Point"
},function(err,docs) {

   // The documents are also mongoose document objects as well
});

See further options on $nearSphere or other operators for options. The main difference here is $maxDistance is in meters when a GeoJSON form is used, rather than radians where otherwise.

There is of course also the $geoNear operator for the aggregation pipeline. This is available as of MongoDB 2.4 and can take other options such as a "query" to narrow results further. The other possible advantage here is that it will "project" a field into your results representing the "distance" from the query point. This can be used in other calculations or custom sorting:

GeoLocation.aggregate(
    [
        { "$geoNear": {
            "near": {
                "type": "Point",
                "coordinates": [parseFloat(req.params.lng), parseFloat(req.params.lat)]
            },
            "distanceField": "distance",
            "maxDistance": distanceInMeters,
            "spherical": true,
            "query": { "loc.type": "Point" }
        }},
        { "$sort": { "distance": -1 } } // Sort nearest first
    ],
    function(err,docs) {

       // These are not mongoose documents, but you can always cast them
    }
);

Other differences to note are that in the standard query form the results are no longer limited to 100 documents as they are in the "command" form. The aggregation $geoNear limits to 100 documents as results by default, but the number of documents returned can be tuned with an additional "limit" option to the pipeline command. The aggregate statement does not "sort" the results other than from the maximum documents to return from the search are the top results given the conditions, but they are not returned in order, so you would need to sort them as shown.

In either case you should be moving your code to use either of these forms as the command form is considered deprecated and will be removed in the future. Whether the mongoose API retains it's method as a "wrapper" for one of these forms is unknown, but mostly unlikely, so it is better to stick with the supported forms.

You can just pass the additional query as an option to the mongoose geoNear function like so:

   // setup geoJson for query
    var geoJson             = {};
    geoJson.type            = "Point";
    geoJson.coordinates     = [parseFloat(req.params.lng), parseFloat(req.params.lat)];

    // setup options for query
    var options             = {};
    options.spherical       = true;
    options.maxDistance     = parseInt(req.params.max)/6370000;
    // you can put any query here to further refine the result.
    options.query = { "loc.type": "Point" };

    // query db with mongoose geoNear wrapper
    GeoLocation.geoNear(geoJson, options, function (err, results, stats) {
        if (err)
            res.send(err);
        res.json(results);
    });
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!