我有一个 mongoDB 集合,其中包含如下所示的文档。我想在所有文档中累计计算事件字段有多少个子文档,该子文档不为空。
{
name: "name1",
events: {
created: {
timestamp: 1512477520951
},
edited: {
timestamp: 1512638551022
},
deleted: null
}
}
{
name: "name2",
events: {
created: {
timestamp: 1512649915779
},
edited: null,
deleted: null
}
}
所以对这两个文档的查询结果应该返回3,因为集合中有3个事件不为null。我无法更改文档的格式以使事件字段成为数组。
最佳答案
你想要$objectToArray
从 MongoDB 3.4.7 或更高版本开始,以便将其作为聚合语句执行:
db.collection.aggregate([
{ "$group": {
"_id": null,
"total": {
"$sum": {
"$size": {
"$filter": {
"input": {
"$objectToArray": "$events"
},
"cond": { "$ne": [ "$$this.v", null ] }
}
}
}
}
}}
])
需要该部分来查看“事件”对象并将每个“键/值”对转换为数组条目。这样你就可以应用$filter
操作以删除 null
“值”(“v”
属性),然后使用 $size
以便计算匹配列表。
所有这些都是在 $group
下完成的使用 $sum
的管道阶段累加器
或者,如果您没有支持版本,则需要执行 mapReduce 和 JavaScript 才能执行相同的“对象到数组”操作:
db.collection.mapReduce(
function() {
emit(null,
Object.keys(this.events).filter(k => this.events[k] != null).length);
},
function(key,values) {
return Array.sum(values);
},
{ out: { inline: 1 } }
)
它使用相同的基本过程,通过以数组形式获取对象键并拒绝那些值为 null
的键,然后获取结果的 length
数组。
由于 JavaScript 评估,这比对应的聚合框架慢得多。但这实际上是一个问题,即您可以使用什么服务器版本来支持您的需求。
关于javascript - 如何计算有条件的子文档的数量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49877621/