【问题标题】:how to use mongodb aggregate and retrieve entire documents如何使用 mongodb 聚合和检索整个文档
【发布时间】:2021-11-09 20:29:41
【问题描述】:

我对 mongodb 的聚合函数感到非常困惑。我只想在我的收藏中找到最新的文档。假设每条记录都有一个“已创建”字段

db.collection.aggregate({
    $group: { 
        _id:0,
        'id':{$first:"$_id"},
        'max':{$max:"$created"}
    }
})

产生正确的结果,但我想要结果中的整个文档?我该怎么做?

这是文档的结构:

{
    "_id" : ObjectId("52310da847cf343c8c000093"),
    "created" : 1389073358,
    "image" : ObjectId("52cb93dd47cf348786d63af2"),
    "images" : [
        ObjectId("52cb93dd47cf348786d63af2"),
        ObjectId("52f67c8447cf343509d63af2")
        ],
    "organization" : ObjectId("522949d347cf3402c3000001"),
    "published" : 1392601521,
    "status" : "PUBLISHED",
    "tags" : [ ],
    "updated" : 1392601521,
    "user_id" : ObjectId("52214ce847cf344902000000")
}

【问题讨论】:

  • 你为什么不使用排序的find
  • 因为我想了解如何使用聚合
  • aggregate 不太适合这种类型的事情,因为您不能轻易地将完整的文档包含在 $group 中,您必须分别引入每个字段。
  • 我在某处看到了一个示例,该示例对聚合结果进行了 forEach-ed,然后使用了 results.push(findOne),但我无法使其工作。我只想弄清楚如何通过一些复杂的关系过滤或什至将聚合字段添加到文档中来获取文档。
  • 我在 cmets 中看到您实际上正在尝试做一些与此不同的事情。您能否编辑您的问题以解释您实际想要达到的目标?请附上一份样本文件。

标签: mongodb aggregation-framework


【解决方案1】:

在文档中我发现 $$ROOT 表达式解决了这个问题。

来自文档: http://docs.mongodb.org/manual/reference/operator/aggregation/group/#group-documents-by-author

【讨论】:

    【解决方案2】:
    query = [
        {
            '$sort': {
                'created': -1
            }
        },
        {
            $group: { 
                '_id':null,
                'max':{'$first':"$$ROOT"}
            }
        }
    ]
    db.collection.aggregate(query)
    

    【讨论】:

      【解决方案3】:
      db.collection.aggregate([
       {
      
        $group: {
         '_id':"$_id",
         'otherFields':{ $push: { fields: $ROOT } }
        } 
       }
      ])
      

      【讨论】:

      • 我们如何将相同的查询转换为使用分页?
      【解决方案4】:

      我想我明白了。例如,我有一个包含一组图像(或指针)的集合。现在我想找到图片最多的文档

      results=[];
      db.collection.aggregate([
          {$unwind: "$images"},
          {$group:{_id:"$_id", 'imagecount':{$sum:1}}},
          {$group:{_id:"$_id",'max':{$max: "$imagecount"}}},
          {$sort:{max:-1}},
          {$group:{_id:0,'id':{$first:'$_id'},'max':{$first:"$max"}}}
      ]).result.forEach(function(d){
          results.push(db.stories.findOne({_id:d.id}));
      });
      

      现在最终的数组将包含图像最多的文档。由于图像是一个数组,我使用 $unwind,然后按文档 id 和 $sum:1 分组,将其通过管道传输到找到最大值的 $group 中,将其管道传输到最大的反向 $sort 中,然后 $group 输出第一个结果。最后我 fetchOne 文档并将其推送到结果数组中。

      【讨论】:

        【解决方案5】:
        db.collection.aggregate([
            {$sort:{created:-1}},
            {$limit:1}
        ])
        

        【讨论】:

        • 请添加更多详细信息以扩展您的答案,例如工作代码或文档引用。
        【解决方案6】:

        您应该使用 db.collection.find() 而不是 db.collection.aggregate():

        db.collection.find().sort({"created":-1}).limit(1)
        

        【讨论】:

        • 这在我的示例中是有道理的,但它仍然没有回答我关于如何在聚合结果中生成整个文档的问题。假设我真的想汇总一组文档,结果不止一个。
        • 在聚合管道中,如果您只有一个 $match 阶段,则将返回整个文档。但是,在 $group 阶段之后,就无法返回整个文档。如果你仔细想想,它甚至没有意义。当您按字段分组时,您将只有在分组阶段为管道中的后续阶段指定的那些字段。由于这些字段可能是 sum() 和 count() 之类的聚合字段(即,它们的值是从多个文档中计算出来的),因此显示与结果对应的整个文档是不合逻辑的。
        • 如果我想从一个集合中获取一个聚合,并将文档字段的一个子集添加到结果中,该怎么办?假设我希望所有文档的某个聚合字段> = 5?例如。显示所有超过 10 个 cmets 的帖子。
        • 我们可以在管道中添加一个$match阶段,在$group阶段之后过滤$group阶段的结果。
        • 阿南德,你能举个语法例子吗?
        猜你喜欢
        • 1970-01-01
        • 2023-03-05
        • 1970-01-01
        • 1970-01-01
        • 2015-05-25
        • 1970-01-01
        • 2020-08-09
        • 2018-12-14
        • 2014-08-02
        相关资源
        最近更新 更多