2014-08-30 100 views
2

我有一個用node.js mongodb和mongoose實現的地理數據api。 我想用兩個條件查詢我的數據。將geoNear查詢與另一個查詢值相結合

首先,我使用geoNear獲取給定半徑內的所有位置,這很好地工作。 第二我想要進一步按類型過濾位置。

這是我的架構:

var GeoLocationSchema = new Schema({ 
    name: String, 
    type: String, 
    loc: { 
     type: { 
      type: String, 
      required: true, 
      enum: ["Point", "LineString", "Polygon"], 
      default: "Point" 
     }, 
     coordinates: [Number] 
    } 
}); 
// ensure the geo location uses 2dsphere 
GeoLocationSchema.index({ loc : "2dsphere" }); 

,這是我geoNear查詢:

router.route("/locations/near/:lng/:lat/:type/:max") 

    // get locations near the get params 
    .get(function(req, res) { 
     // 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; 

     // query db with mongoose geoNear wrapper 
     GeoLocation.geoNear(geoJson, options, function (err, results, stats) { 
      if (err) 
       res.send(err); 
      res.json(results); 
     }); 
    }); 

是它在某種程度上可以將geoNear查詢與查詢合併爲特定類型的位置或可我以某種方式過濾結果?

在此先感謝。

+0

使用'$ geoNear'聚集階段作爲管道的第一階段。您可以使用'$ match'階段等進一步設置條件/操作。 – wdberkeley 2014-08-31 15:07:57

回答

4

只要您的MongoDB服務器足夠新,作爲2.6或更高的版本,那麼這個功能實際上已經移到了通用查詢引擎。此處的mongoose方法包含.runCommand()表單,該表單在所有將來的版本中都被棄用,所以這只是將標準查詢與其他運算符一起放置的問題。

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 
}); 

有關選項,請參見$nearSphere或其他運營商的更多選項。這裏的主要區別是$maxDistance在使用GeoJSON格式時的單位是米,而不是其他情況下的弧度。

聚合流水線當然還有$geoNear運算符。這從MongoDB 2.4開始是可用的,並且可以採用其他選項,例如「查詢」來進一步縮小結果。這裏的另一個可能的優點是它將一個字段「投影」到代表查詢點的「距離」的結果中。這可以在其他計算或自定義排序中:

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 
    } 
); 

其他方面的差異需要注意的是,在標準查詢形成的結果不再僅限於100個文件,因爲它們是在「命令」形式。默認情況下,聚合$geoNear將限制爲100個文檔作爲結果,但返回的文檔數量可以通過管道命令的附加「限制」選項進行調整。除了從搜索返回的最大文檔之外,彙總語句不「排序」結果是給定條件的最高結果,但它們不是按順序返回的,因此您需要按照顯示的順序對它們進行排序。

無論哪種情況,您都應該將代碼移至其中一種形式,因爲命令表單被視爲棄用,將來會被刪除。貓鼬API是否保留它作爲這些形式之一的「包裝器」的方法是未知的,但大多不太可能,所以最好堅持使用支持的形式。

+0

感謝您提供非常詳細的答案! – arkhon 2014-09-04 08:42:57

2

你可以只通過附加的查詢作爲一個選項,以貓鼬geoNear功能,像這樣:

// 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); 
    }); 
+0

它不適用於貓鼬4.3.6 – Max 2016-07-19 05:25:11

相關問題