【问题标题】:MongoDB: Retrieve most referenced documentMongoDB:检索引用最多的文档
【发布时间】:2014-10-27 09:24:54
【问题描述】:

我有一个 MongoDB 集合(称为“链接”),其中包含类似这样的文档:

{
    "_id" : ObjectId("544bc8abd4c66b0e3cf12665"),
    "name" : "Pet 4056 AgR",
    "file" : "P0001J01",
    "quotes" : [
        {
            "_id" : ObjectId("544bc8afd4c66b0e3cf15173"),
            "name" : "Pet 4837 ED",
            "file" : "P1103J03"
        },
        {
            "_id" : ObjectId("544bc8b6d4c66b0e3cf19425"),
            "name" : "ACO 845 AgR",
            "file" : "P2810J07"
        },
        {
            "_id" : ObjectId("544bc8afd4c66b0e3cf14a77"),
            "name" : "ACO 1574 AgR",
            "file" : "P0924J05"
        }
    ]
}

在我的数据库中,这意味着该文档引用了其他 3 个文档。 对于每个文档,在其quotes 数组中没有两个具有相同 id/name/file 的文档。 name 字段在集合中是唯一的。

现在,我需要获取引用最多的文档。它是出现在大多数quotes 数组中的文档。我怎样才能做到这一点? 我相信这是通过聚合实现的,但我不知道该怎么做,尤其是因为名称在数组中。

谢谢! :)

【问题讨论】:

  • 如何在每个文档中添加一个额外的字段来保存引用计数?因此,您可以在其他文档引用它时更新和维护引用计数,然后轻松地对其进行查询和排序。
  • 没想到,能做到!但是,我认为按照您在答案中的建议进行放松和分组会更安全,以防将来有人想要添加更多文档而忘记更新引用计数。这有意义吗?

标签: mongodb mongodb-query aggregation-framework


【解决方案1】:

您可以使用聚合框架执行此操作,但使用数组的一个关键特性是您使用$unwind 管道操作首先将数组内容“反规范化”为单独的文档:

db.links.aggregate([
    // Unwind the array
    { "$unwind": "$quotes" },

    // Group by the inner "name" value and count the occurrences
    { "$group": {
        "_id": "$quotes.name",
        "count": { "$sum": 1 }
    }},

    // Sort to the highest count on top
    { "$sort": { "count": 1 } },

    // Just return the largest value
    { "$limit": 1 }

])

所以$unwind 在这里所做的是对于每个数组元素,它获取拥有该数组的“外部”文档的副本,并生成一个包含外部且仅包含单个数组元素的新文档。基本上是这样的:

{
    "_id" : ObjectId("544bc8abd4c66b0e3cf12665"),
    "name" : "Pet 4056 AgR",
    "file" : "P0001J01",
    "quotes" : 
        {
            "_id" : ObjectId("544bc8afd4c66b0e3cf15173"),
            "name" : "Pet 4837 ED",
            "file" : "P1103J03"
        }
},
{
    "_id" : ObjectId("544bc8abd4c66b0e3cf12665"),
    "name" : "Pet 4056 AgR",
    "file" : "P0001J01",
    "quotes" : 
        {
            "_id" : ObjectId("544bc8b6d4c66b0e3cf19425"),
            "name" : "ACO 845 AgR",
            "file" : "P2810J07"
        }
}

这允许其他聚合管道阶段像访问任何普通文档一样访问内容,因此您可以$group“quotes.name”上的出现而不会出现问题。

仔细查看所有aggregation pipeline operators,值得了解他们都在做什么。

【讨论】:

  • 非常好的解决方案,展开使它更清晰。我相信"count": 1 位应该是"count": -1 降序排列,对吧?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-25
  • 2016-03-15
  • 1970-01-01
  • 1970-01-01
  • 2016-12-15
  • 2016-03-02
相关资源
最近更新 更多