2016-08-05 40 views
3

我試圖過濾返回的數據集與流星的find().fetch()只包含一個對象,它不顯示非常有用,如果我查詢單個子文檔,而是我接收幾個,有些甚至不包含任何匹配的術語。流星:只返回集合中的嵌套數組中的單個對象

我有一個簡單的混合數據收集,看起來像這樣:

{ 
    "_id" : ObjectId("570d20de3ae6b49a54ee01e7"), 
    "name" : "Entertainment", 
    "items" : [ 
     { 
      "_id" : ObjectId("57a38b5f2bd9ac8225caff06"), 
      "slug" : "this-is-a-long-slug", 
      "title" : "This is a title" 
     }, 
     { 
      "_id" : ObjectId("57a38b835ac9e2efc0fa09c6"), 
      "slug" : "mc", 
      "title" : "Technology" 
     } 
    ] 
} 
{ 
    "_id" : ObjectId("570d20de3ae6b49a54ee01e8"), 
    "name" : "Sitewide", 
    "items" : [ 
     { 
      "_id" : ObjectId("57a38bc75ac9e2efc0fa09c9"), 
      "slug" : "example", 
      "name" : "Single Example" 
     } 
    ] 
} 

我可以很容易地嵌套items陣列與MongoDB的殼,因爲這在查詢特定對象:

db.categories.find({ "items.slug": "mc" }, { "items.$": 1 }); 

這將返回良好的數據,它只包含我想要使用的單個對象:

{ 
    "_id" : ObjectId("570d20de3ae6b49a54ee01e7"), 
    "items" : [ 
     { 
      "_id" : ObjectId("57a38b985ac9e2efc0fa09c8") 
      "slug" : "mc", 
      "name" : "Single Example" 
     } 
    ] 
} 

但是,如果內流星類似的查詢被直接嘗試:

/* server/publications.js */ 
Meteor.publish('categories.all', function() { 
    return Categories.find({}, { sort: { position: 1 } }); 
}); 
/* imports/ui/page.js */ 
Template.page.onCreated(function() { 
    this.subscribe('categories.all'); 
}); 
Template.page.helpers({ 
    items: function() { 
     var item = Categories.find(
      { "items.slug": "mc" }, 
      { "items.$": 1 }) 
     .fetch(); 
     console.log('item: %o', item); 
    } 
}); 

的結果是不理想的,因爲它返回整個匹配塊,以及嵌套items陣列中的每個對象:

{ 
    "_id" : ObjectId("570d20de3ae6b49a54ee01e7"), 
    "name" : "Entertainment", 
    "boards" : [ 
     { 
      "_id" : ObjectId("57a38b5f2bd9ac8225caff06") 
      "slug" : "this-is-a-long-slug", 
      "name" : "This is a title" 
     }, 
     { 
      "_id" : ObjectId("57a38b835ac9e2efc0fa09c6") 
      "slug" : "mc", 
      "name" : "Technology" 
     } 
    ] 
} 

我當然可以用一個for循環來進一步篩選返回的遊標,以獲得所需的對象,但是在處理較大的數據集時,這看起來不可取,效率極低。

我不明白爲什麼流星的find返回的數據集完全不同於MongoDB的shell find,唯一合理的解釋是兩個函數簽名都不一樣。

我是否應該將嵌套集合分解爲更小的集合並採用更多關係數據庫方法(即存儲對ObjectID的引用)和查詢集合之間的數據,還是有更強大的方法來有效地過濾大型數據集合成只包含匹配對象的單個對象,如上所示?

+0

流星的客戶端實現被稱爲MiniMongo。它只實現MongoDB選擇器的一個子集。 – MasterAM

回答

1

Meteor使用的Mongo客戶端實現稱爲minimongo。它目前僅實現可用Mongo功能的一個子集。 Minimongo目前不支持基於$的預測。從流星API的Field Specifiers部分:

場運營商,如$ $和elemMatch不可在客戶端呢。

這是您在客戶端和Mongo shell之間獲得不同結果的原因之一。你可以用你的原始查詢得到最接近的是結果,你會通過改變"items.$""items"得到:

Categories.find(
    { "items.slug": "mc" }, 
    { "items": 1 } 
).fetch(); 

這個查詢仍然是不完全正確,雖然。 Minimongo期望您的第二個find參數是docs中列出的允許的選項參數之一。爲了例如過濾fields,你必須做一些事情,如:

Categories.find(
    { "items.slug": "mc" }, 
    { 
    fields: { 
     "items": 1 
    } 
    } 
).fetch(); 

在客戶端(與Minimongo),那麼你就需要進一步的篩選結果自己。

沒有這樣做,雖然另一種方式。如果您在服務器上運行蒙戈查詢,你會不會使用Minimongo,這意味着預測的支持。作爲一個簡單的例子,請嘗試以下操作:

/server/main.js

const filteredCategories = Categories.find(
    { "items.slug": "mc" }, 
    { 
    fields: { 
     "items.$": 1 
    } 
    } 
).fetch(); 
console.log(filteredCategories); 

的投影會工作,並記錄結果將與您直接使用蒙戈控制檯時看到的結果。而不是在客戶端運行Categories.find,您可以創建一個Meteor方法,在服務器上調用Categories.find,並將結果返回給客戶端。

+0

我已經決定在客戶端使用下劃線的'_.filter'方法和服務器端的Meteor方法進行混合操作,以獲得更精細的結果。謝謝! – nitomoe

+0

這是一個非常有用的答案!特別是需要在服務器上進行彙總的說明。謝謝! – brianjlennon

相關問題