聚合框架是這樣的理想選擇。考慮運行以下管道以獲得所需的結果。
pipeline = [
{
"$match": {
"name": "james",
"books.year": 1990
}
},
{
"$project": {
"numberOfBooks": {
"$size": {
"$filter": {
"input": "$books",
"as": "el",
"cond": { "$eq": [ "$$el.year", 1990 ] }
}
}
}
}
}
];
db.collection.pipeline(pipeline);
上述管道使用可用MongoDB的3.2新操作者以產生滿足指定條件,即它過濾不滿足標準外元素的數組。流水線初始化爲流水線優化策略,以儘早過濾掉進入聚合流水線的文檔。
The $size
運算符接受單個表達式作爲參數,然後給你在結果數組中的元素數,因此你有你想要的書數。
對於不使用早期版本沒有找到操作,請考慮以下流水線操作的替代解決方案:
pipeline = [
{
"$match": {
"name": "james",
"books.year": 1990
}
},
{
"$project": {
"numberOfBooks": {
"$size": {
"$setDifference": [
{
"$map": {
"input": "$books",
"as": "el",
"in": {
"$cond": [
{ "$eq": [ "$$el.year", 1990 ] },
"$$el",
false
]
}
}
},
[false]
]
}
}
}
}
];
db.collection.pipeline(pipeline);
的$project
流水線階段涉及fittering書籍數組以便刪除1990年以前的文件。這可以通過$setDifference
和$map
運營商。
的$map
操作在本質上創建保持值作爲一個子表達式到數組的每個元素的邏輯評價的結果的新的數組字段。 $setDifference
運算符然後返回一個集合,其中元素出現在第一個集合中,但不出現在第二個集合中;即執行第二組相對於第一組的相對補償。在這種情況下,它將返回包含1990年元素的最終書籍數組,然後$size
計算結果數組中的元素數量,從而爲您提供書籍數量。
對於使用$unwind
操作者,銘記(由於從@BlakesSeven評價此見地響應)中的溶液:
由於只有返回單個文檔除了一個空值 鍵和一個計數之外,沒有更多的機會破壞這個限制 比以前的操作具有相同的輸出。這並不是說 $ unwind「打破了限制」,而是它「爲每個陣列條目生成每個 文檔的副本」,其使用更多的存儲器(可能的存儲器 對總存儲器的10%的聚合流水線上限),因此也是 需要「時間」產生以及「時間」來處理。
和作爲最後的手段,運行下面的管道:
pipeline = [
{
"$match": {
"name": "james",
"books.year": 1990
}
},
{ "$unwind": "$books" },
{
"$match": { "books.year": 1990 }
},
{
"$group": {
"_id": null
"count": { "$sum": 1 }
}
}
]
db.collection.pipeline(pipeline)
的可能的複製[MongoDB的:計數項的數組中的數](http://stackoverflow.com/questions/21387969/mongodb-count-the-number-of-an-an-an-array) –
嚴重的是,如果只有一個文檔要從這個返回,那麼聚合框架(它可以從數組中獲取大小並將其過濾掉首先也是)在這裏將是一個糟糕的選擇。更好的方法是僅測試匹配條件的文檔中返回的數組大小。 'db.collection(collectionName).findOne({「name」:「james」,「books.year」:1990},function(err,result){console.log(result.books.filter(function(book){ return book.year == 1990})。length)})'。很簡單的東西。只有在您打算使用該數字時纔會彙總,以及使用該數字進行彙總。 –