2013-04-22 33 views
3

我使用Mongoose 3.5.3和Node.js 0.8.8,我很驚訝地發現距離給定點的距離沒有返回到結果中。是否有可能允許返回距離?它必須擁有它,因爲我的結果似乎按照預期的距離排序。如何在地理空間搜索中返回與MongoDB和Mongoose的距離?

exports.nearBuilding = function (req, res, next) { 
    var area = { 
     center: [parseFloat(req.params.longitude), parseFloat(req.params.latitude)], 
     radius: parseFloat(req.params.distance)/3963.192 }; 

    var query = Building.find().where('coords').within.centerSphere(area); 

    query.exec(function (error, docs) { 
     var records = {'records': docs}; 
     if (error) { 
      process.stderr.write(error); 
      res.send(error, 500); 
     } 
     if (req.params.callback !== null) { 
      res.contentType = 'application/javascript'; 
     } 
     res.send(records); 
     return next(); 
    }); 
}; 

回答

5

可以使用geoNear函數返回距離:

Building.collection.geoNear(longitude, latitude, {maxDistance: radius }, cb); 

這裏有API選項:

/** 
* Execute the geoNear command to search for items in the collection 
* 
* Options 
* - **num** {Number}, max number of results to return. 
* - **maxDistance** {Number}, include results up to maxDistance from the point. 
* - **distanceMultiplier** {Number}, include a value to multiply the distances with allowing for range conversions. 
* - **query** {Object}, filter the results by a query. 
* - **spherical** {Boolean, default:false}, perform query using a spherical model. 
* - **uniqueDocs** {Boolean, default:false}, the closest location in a document to the center of the search region will always be returned MongoDB > 2.X. 
* - **includeLocs** {Boolean, default:false}, include the location data fields in the top level of the results MongoDB > 2.X. 
* - **readPreference** {String}, the preferred read preference ((Server.PRIMARY, Server.PRIMARY_PREFERRED, Server.SECONDARY, Server.SECONDARY_PREFERRED, Server.NEAREST). 
* 
* @param {Number} x point to search on the x axis, ensure the indexes are ordered in the same order. 
* @param {Number} y point to search on the y axis, ensure the indexes are ordered in the same order. 
* @param {Objects} [options] options for the map reduce job. 
* @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the geoNear method or null if an error occured. 
* @return {null} 
* @api public 

在你的情況,你會做這樣的事情:

 exports.nearBuilding = function (req, res, next) { 

     var query = Building.collection.geoNear(parseFloat(req.params.longitude), parseFloat(req.params.latitude), { distance: parseFloat(req.params.distance)/3963.192}, function (error, docs) { 

      if (error) { 
       process.stderr.write(error); 
       res.send(error, 500); 
      } 
      if (req.params.callback !== null) { 
       res.contentType = 'application/javascript'; 
      } 
      // Docs are turned as an array of objects that contain distance (dis) and the object (obj). 
      // Let's concatenate that into something cleaner - i.e. the distance as part of object 

      var results = [] 
      docs.forEach(function(doc) { 
       doc.obj.distance = doc.dis; 
       results.push(doc.obj); 
      }); 
      var records = {'records': results};  

      res.send(records); 
      return next(); 
     }); 
    }; 
+0

出衆!我稍微更新了一下,這樣forEach就不會出錯,但這正是我之後... thx! – occasl 2013-05-24 21:32:57

3

當前(3 0.8)貓鼬的構建提供了一個Model方法geoNear爲此目的:

Building.geoNear(
    [long, lat], 
    { maxDistance: 300, spherical: true }, 
    function(err, results, stats) { 
     // results is an array of result objects like: 
     // {dis: distance, obj: doc} 
    } 
); 
5

如果使用2dsphere座標(你應該)代碼應如下。距離d以米爲單位。

var point = { coordinates: [lng, lat], type: 'Point' };   
 

 
Entity.geoNear(point, {maxDistance: d, spherical: true}, function(err, docs) { 
 
    if (err) { return next(err); } 
 

 
    var entities = []; 
 

 
    docs.forEach(function(doc) { 
 
    doc.obj.distance = doc.dis; 
 
    entities.push(doc.obj); 
 
    }); 
 

 
    res.json(entities); 
 
});

相關問題