javascript - 如何计算有条件的子文档的数量

标签 javascript mongodb mongodb-query aggregation-framework

我有一个 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/

相关文章:

JavaScript tCal 日期格式

java - 将文档从一个集合移动到另一个集合会覆盖该文档

mysql - 在 grails3 中使用 mongodb 和 hibernate

node.js - 通过数组聚合对文档进行评分

javascript - AngularJS 或 CSS - 具有多行和第一列的表的问题已修复

javascript - 允许 float 元素水平溢出

javascript - Safari 上的 jQuery css 背景图像在重新访问时再次下载图像

mongodb - mongodb连接grafana的方式

mongodb - 如何在mongodb中找到两个日期之间的时差

mongodb - 在 mongo 中,只有当记录尚不存在时,我才能插入记录