聚合框架是这样的理想选择。考虑运行以下管道以获得所需的结果。
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)})'。很简单的东西。只有在您打算使用该数字时才会汇总,以及使用该数字进行汇总。 –