2014-04-08 39 views
0

我正在搜索一系列商店。商店有一個嵌入式地點集合。我的目標是返回在地理位置附近有商店的商店集合,並且僅返回那些位置在之內的商店在Mongoose附近使用elemMatch

我可以成功地限制查詢只返回商店使用「近」


Store 
    .where('isActive').equals(true) 
    .where('outlets.location') 
    .near({ center: [153.027117, -27.468515], maxDistance: 1000/6378137, spherical: true }) 
    .where('outlets.isActive').equals(true) 
    .where('products.productType').equals('53433f1f3e02e39addde1954') 
    .where('products.isActive').equals(true) 
    .select('name outlets') 
    .select({'products': {$elemMatch: {'isActive': true, 'productType': '53433f1f3e02e39addde1954'}}}) 
    .select('name outlets') 
    .execQ() 
    .then(function (results) { 
    console.log(results); 
    }) 
    .fail(function (err) { 
    console.log(err); 
    }) 
    .done(); 

具有在特定位置的出口我的問題是,這家店的文檔返回所有的網點,而不僅僅是出口與地理位置相匹配。我嘗試過使用elemMatch,像我對產品做過的那樣;

。選擇({ '網點':{$ elemMatch:{ '位置':{鄰近:{中心:[153.027117,-27.468515],maxDistance:六百三十七萬八千一百三十七分之一萬,球形:真}}}}} )

但是它返回一個空數組。在elemMatch子句中可以使用near操作符嗎?我做錯了嗎?是否有更高效/更快/更好的方式來實現目標?

+0

答案中有些東西不清楚嗎?我認爲情況已經非常明確地解釋了。 –

回答

1

我明白你在這裏想要做什麼,但在這種設計中似乎有一些缺陷。雖然不完全是你的文檔結構我看你正在嘗試做這樣的事情:

{ 
    "_id" : ObjectId("5344badd519563414f23fdf8"), 
    "store" : "Mine", 
    "outlets" : [ 
      { 
        "name" : "somewhere", 
        "loc" : { 
          "type" : "Point", 
          "coordinates" : [ 
            150.975131, 
            -33.8440366 
          ] 
        } 
      }, 
      { 
        "name" : "else", 
        "loc" : { 
          "type" : "Point", 
          "coordinates" : [ 
            151.3651524, 
            -33.8389783 
          ] 
        } 
      } 
    ] 
} 
{ 
    "_id" : ObjectId("5344be6f519563414f23fdf9"), 
    "store" : "Another", 
    "outlets" : [ 
      { 
        "name" : "else", 
        "loc" : { 
          "type" : "Point", 
          "coordinates" : [ 
            151.3651524, 
            -33.8389783 
          ] 
        } 
      }, 
      { 
        "name" : "somewhere", 
        "loc" : { 
          "type" : "Point", 
          "coordinates" : [ 
            150.975131, 
            -33.8440366 
          ] 
        } 
      } 
    ] 
} 

所以基本上你似乎試圖窩在陣列內的出口位置在頂層文件。

我在這裏指的是一個缺陷是,通過設計,任何類型的「近」基於查詢將返回多於1個結果。當你看到目的時,這似乎是合乎邏輯的。你當然可以通過「maxDistance」來修改這個結果,但通常它會大於1.

所以唯一的辦法就是將光標返回的結果作爲一個「最近」的響應。還要注意的是,對於某些操作,這些結果不一定是「排序」的「最近的響應優先」。

現在,因爲這些結果實際上包含在文檔數組中,請記住.find()本身並不實際「過濾」當然文檔將包含所有的數組內容

如果您嘗試使用位置$運算符「投影」,那麼問題會回落到原始點,因爲沒有單個的實際值匹配,所以不可能爲匹配元素返回一個「索引」值,如果你確實嘗試了這個,你總會得到默認索引值0,所以只返回第一個元素。

如果你認爲你可以逃跑來聚合,並試圖實際「解規範」數組條目,那麼你會不走運,因爲由於需要使用第一個階段的索引任何聚合管道語句。

因此,總結這樣的嵌入式條目不適合這種設計,你需要在這些商店位置上進行地理空間匹配。該位置是在一個單獨的收集更好:

{ 
    "_id" : ObjectId("5344bec7519563414f23fdfa"), 
    "store": "Mine" 
    "name" : "else", 
    "loc" : { 
      "type" : "Point", 
      "coordinates" : [ 
        151.3651524, 
        -33.8389783 
      ] 
    } 
} 
{ 
    "_id" : ObjectId("5344bed5519563414f23fdfb"), 
    "store": "Mine" 
    "name" : "somewhere", 
    "loc" : { 
      "type" : "Point", 
      "coordinates" : [ 
        150.975131, 
        -33.8440366 
      ] 
    } 
} 

因此,這將讓你「限制」結果到「最近」的比賽被限制設置爲1,您還可以包括任何必要的值,如在您的過濾中使用的「商店」。如果你需要的話,除了需要過濾的內容之外,還可以包含其他信息,或者只需將ObjectId值放入原始對象的數組中,或者甚至可以爲兩個集合重複。

但是,由於這些查詢的本質不僅僅是返回1個匹配,那麼您將無法使這個工作在嵌入式文檔上。因此,您的解決方案需要對整個架構進行一些更改。

+0

謝謝尼爾!這是一個很好的問題總結。展望未來,我會將網點轉移到他們自己的文檔中。 – Robert