Mongodb聚合大型数据集的查询计数记录

时间:2016-03-02 18:54:04

标签: mongodb aggregation-framework

我正在尝试查询errorlog集合中的所有数据,而同一查询中的 会为每个错误日志条目获取相关irs_documents的计数。

问题是irs_documents集合中有太多记录要执行$ lookup。

是否有一种在一个MongoDB查询中执行此操作的高效方法?

尝试失败

db.getCollection('errorlog').aggregate(
  [
    {
        $lookup: {
          from: "irs_documents",
          localField: "document.ssn",
          foreignField: "ssn",
          as: "irs_documents"
        }
    },
    {
        $group: {
            _id: { document: "$document", error: "$error" },
            logged_documents: { $sum : 1 }
        }
    }
  ]
)

错误

Total size of documents in $lookup exceeds maximum document size

显然,此解决方案无效。 MongoDB实际上是试图用$ lookup来收集整个文档,我只想要一个计数。

“errorlog”集合示例数据:

/* 1 */
{
    "_id" : ObjectId("56d73955ce09a5a32399f022"),
    "document" : {
        "ssn" : 1
    },
    "error" : "Error 1"
}

/* 2 */
{
    "_id" : ObjectId("56d73967ce09a5a32399f023"),
    "document" : {
        "ssn" : 2
    },
    "error" : "Error 1"
}

/* 3 */
{
    "_id" : ObjectId("56d73979ce09a5a32399f024"),
    "document" : {
        "ssn" : 3
    },
    "error" : "Error 429"
}

/* 4 */
{
    "_id" : ObjectId("56d73985ce09a5a32399f025"),
    "document" : {
        "ssn" : 9
    },
    "error" : "Error 1"
}

/* 5 */
{
    "_id" : ObjectId("56d73990ce09a5a32399f026"),
    "document" : {
        "ssn" : 1
    },
    "error" : "Error 8"
}

“irs_documents”集合样本数据

/* 1 */
{
    "_id" : ObjectId("56d73905ce09a5a32399f01e"),
    "ssn" : 1,
    "name" : "Sally"
}

/* 2 */
{
    "_id" : ObjectId("56d7390fce09a5a32399f01f"),
    "ssn" : 2,
    "name" : "Bob"
}

/* 3 */
{
    "_id" : ObjectId("56d7391ace09a5a32399f020"),
    "ssn" : 3,
    "name" : "Kelly"
}

/* 4 */
{
    "_id" : ObjectId("56d7393ace09a5a32399f021"),
    "ssn" : 9,
    "name" : "Pippinpaddle-Oppsokopolis"
}

1 个答案:

答案 0 :(得分:1)

错误是不言自明的。 Lookup实际上是将两个文档组合成单个BSON文档,因此MongoDB文档大小限制正在咬你。

你需要问问自己,在一次操作中执行这两个动作是绝对必要的吗?如果是,请按照以前版本的MongoDB中的方式执行此操作,其中不支持$ lookup。

说,执行两个查询并在您的客户端执行合并。

  

选项#1:您可以在irs_documents上聚合并将计算结果导出到另一个集合中。因为,每个文档中的对象很少,我不认为你会遇到问题。 ,您可能遇到内存问题并被迫使用磁盘进行聚合框架。尝试以下解决方案,看看它是否有效。

db.irs_documents.aggregate([
{
  $group:{_id:"$ssn", count:{$sum:1}}  
},
{
  $out:"irs_documents_group"
}]);

db.errorlog.aggregate([
    {
        $lookup: {
          from: "irs_documents_group",
          localField: "document.ssn",
          foreignField: "ssn",
          as: "irs_documents"
        }
    },
    {
        $group: {
            _id: { document: "$document", error: "$error" },
            logged_documents: { $sum : 1 }
        }
    }
  ])
  

选项#2:如果上述解决方案无效,您可以随时使用map reduce,虽然它不是一个优雅的解决方案,但可以使用。