MongoDB / Mongoose - Aggregation with geoNear and attached documents

I am using the node-geoip module and executing an aggregation request. The schema with which I execute the query is as follows:

var mongoose = require('mongoose'); require('./location.js'); module.exports = mongoose.model('Region',{ attr1: Number, attr2: String, attr3: String, locations:[mongoose.model('Location').schema] }); 

and

 var mongoose = require('mongoose'); module.exports = mongoose.model('Location',{ attr1: Number, latlong: { type: [Number], index: '2d' }, }); 

I need to perform the $ geoNear operation in an aggregation request, but I ran into a few problems. Firstly, here is my aggregation method:

 var region = require('../models/region'); var geo = geoip.lookup(req.ip); region.aggregate([ {$unwind: "$locations"}, {$project: { attr1 : 1, attr2 : 1, locations : 1, lower : {"$cond" : [{$lt: [ '$locations.attr1', '$attr1']}, 1, 0]} }}, { $geoNear: { near: { type:"Point", '$locations.latlong': geo.ll }, maxDistance: 40000, distanceField: "dist.calculated" } }, { $sort: { 'locations.attr1': -1 } }, {$match : {lower : 1}}, { $limit: 1 } ], function(err,f){...}); 

The first problem I get is that obviously geoNear should be in the first pipeline stage: exception: $geoNear is only allowed as the first pipeline stage . So my question is: can I search for geoNear in subdocuments without untying them? If so, how?

Another error message I get is errmsg: \"exception: 'near' field must be point\" . What does this mean and what does it mean for my code? I tried using near as:

 near: { type:"Point", '$locations.latlong': geo.ll }, 
+7
javascript mongodb mongoose aggregation-framework geolocation
source share
1 answer

First caveat: I'm not an Node / Mongoose expert, so I hope you can translate common formats to Node / Mongoose.

For the error:

  errmsg: "exception: 'near' field must be point" 

For the '2d' index, this cannot be GeoJson and should instead be the “old coordinate pair”. eg.

 { "$geoNear": { "near": geo.ll, "maxDistance": 40000, "distanceField": "dist.calculated" } } 

If you want to use GeoJSON, you will need to use the "2dsphere" index.

With this change, the $ geoNear query will work with an array of points in the query. Shell example:

 > db.test.createIndex({ "locations": "2d" }) > db.test.insert({ "locations": [ [1, 2], [10, 20] ] }); > db.test.insert({ "locations": [ [100, 100], [180, 180] ] }); > db.test.aggregate([{ "$geoNear": { "near": [10, 10], "maxDistance": 40000, "distanceField": "dist.calculated", num: 1 } }]); { "result": [{ "_id": ObjectId("552aaf7478dd9c25a3472a2a"), "locations": [ [ 1, 2 ], [ 10, 20 ] ], "dist": { "calculated": 10 } }], "ok": 1 } 

Please note that you get only one distance per document (the nearest point), which semantically does not coincide with the unwinding process, and then determines the distance to each point. I cannot be sure that this is important for your use case.

+4
source share

All Articles