2014-10-01 60 views
0

想象電影的集合(存儲在MongoDB的集合),每一個看起來像這樣:

{ 
    _id: 123456, 
    name: 'Blade Runner', 
    buyers: [1123, 1237, 1093, 2910] 
} 

我想電影列表,每一個與表明買方2910(例如)是否購買了它。

任何想法?

我知道我可以將[1123,1237,1093,2910]更改爲[{id:1123},{id:1237},{id:1093},{id:2910}],以允許使用$ elemMatch在投影中,但寧願不要觸摸結構。我也知道我也許可以使用$ unwind操作符(在聚合框架內),但在買家有數千個值(基本上每個文檔在匹配前將內容分解爲數千個拷貝)的情況下,這似乎非常浪費。

還有其他想法嗎?我在這裏錯過了很簡單的東西嗎?

回答

1

可以使用$setIsSubset集成算做到這一點:

var buyer = 2910; 
db.movies.aggregate(
    {$project: { 
     name: 1, 
     buyers: 1, 
     boughtIt: {$setIsSubset: [[buyer], '$buyers']} 
    }} 
) 

這將會給你一個boughtIt領域的所有電影文件添加指示buyer是否包含在電影的buyers陣列英寸

該操作符是在MongoDB 2.6中添加的。

1

這裏不太確定你的意圖,但你不需要改變結構只是爲了在投影中使用$elemMatch。你可以只發出如下:

db.movies.find({},{ "buyers": { "$elemMatch": { "$eq": 2910 } } }) 

這將返回數組元素過濾出的「買家」被指出,或什麼地方,這是不存在的。確實指出這裏使用的$eq運算符沒有實際記錄,但它確實存在。所以,你可以用這種方式構造一個條件,這可能並不是很清楚。

儘管您迴歸「一切」,無論「買方」是否存在,但對我來說似乎有點浪費。所以,「查詢」似乎比投影更合乎邏輯:

db.movies.find({ "buyers": 2910 }) 

和可選要麼只是只保留匹配結果:

db.movies.find({ "buyers": 2910 },{ "buyers.$": 1}) 

在聚合框架Set operators給你$project可以做更多的選擇更多來改變文件。但是如果你只是想知道某人是否「購買」了該項目,那麼「查詢」似乎是符合邏輯和最快的方式。