mongodb - 聚合 $accumulator + $project

标签 mongodb mongoose aggregation-framework

目前,我在 MongoDB 中有很多文档。我需要做的是找到每个唯一的字段、键和值,并计算每个字段、键和值存在的总数。 举个例子,如果我们有文档:

[{ value1: 'same', value2: 'unique'}, { value1: 'same', value2: 'unique1' }, { value3: 'new' }] 

输出应该是(与此类似的内容 - 确切的格式并不重要)

[
    {
        value1: { 
            same: 2, // there are 2 documents with { value1: 'same' }
        },
        value2: {
            unique: 1, // there is 1 document with { value2: 'unique' }
            unique1: 1, // there is 1 document with { value2: 'unique1' }
        },
        value3: {
            new: 1, // there is 1 document with { value3: 'new' }
        },
    }
]

我不确定是否有一种好的、高性能的方法可以通过聚合来做到这一点(我们可以对所有属性进行“展开”,但这将为每个属性创建一个新文档,然后循环每个属性,这对性能非常不利)

我有两种方法,看起来非常接近实现总体想法,但我对这两种方法都有问题。

  1. $函数+全局变量。

如果我可以循环每个文档并使用全局“输出”变量,我可以简单地为每个文档更新此变量,在 JS 中完成工作,然后在最后返回该变量。

我试图为此做的“概念证明”是简单地增加一个全局变量,然后将该变量作为文档返回。

[{
    // write a custom JS function that has access to the current document
    $replaceRoot: {
        newRoot: {
            $function: {
                body: function (doc: any, TOTAL_COUNT: any) {
                    if (!TOTAL_COUNT) TOTAL_COUNT = 0; // set the initial value
                    TOTAL_COUNT++; // this doesn't truly increment the "$TOTAL_COUNT" variable :(
                    return { total_count: TOTAL_COUNT };
                },
                args: ['$$ROOT', '$TOTAL_COUNT'],
                lang: 'js',
            },
        },
    },
},
]
  • 累加器
  • 我非常确定“正确”的方法是使用累加器(因为它们是为了存储持久信息)。但是,累加器唯一可用的方法是 $group、$bucket 和 $bucketAuto。

    据我所知,这些都不允许我简单地“返回输出”,类似于 $project 或 $replaceRoot。

    一旦我有了概念验证,我很乐意使用累加器或函数,然后自己完成剩下的工作:)

    感谢您的任何帮助/建议!非常感谢:)

    最佳答案

    您可以先将文档转换为 k-v 元组数组。根据需要 $unwind 数组和 $group

    db.collection.aggregate([
      {
        "$project": {
          kv: {
            "$objectToArray": "$$ROOT"
          }
        }
      },
      {
        "$unwind": "$kv"
      },
      {
        "$match": {
          "kv.k": {
            $ne: "_id"
          }
        }
      },
      {
        $group: {
          _id: {
            k: "$kv.k",
            v: "$kv.v"
          },
          cnt: {
            $sum: 1
          }
        }
      }
    ])
    

    这是Mongo Playground供您引用。

    关于mongodb - 聚合 $accumulator + $project,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73886502/

    相关文章:

    java - 如何在 MongoDB Java 驱动程序中编写带有添加操作的 group by

    Mongodb聚合框架: Does $group use index?

    mongodb - C# MongoDb 连接到副本集问题

    node.js - 使用 Mongoose 查找所有文件

    node.js - Mongoose:无法使用 $addToSet 或 $push 将新对象添加/推送到数组

    node.js - 无法使用 mongoose.connect 连接到 Mongodb

    MongoDB 将两个字段中的字符串连接到第三个字段中

    javascript - MongoDB:填充或查询两个集合

    node.js - 使用 MongoDB 在 Node.js 中扩展,我应该什么时候一次查询所有 ID,还是并行查询每个 ID?

    node.js - findOneAndUpdate upsert 后 try catch _id