【问题标题】:MongoDB aggregate different collectionsMongoDB聚合不同的集合
【发布时间】:2022-02-26 04:02:25
【问题描述】:

我从昨天开始就一直在尝试做这个聚合,但没有运气,希望你们能给我一些想法。一点背景知识,我有 2 个集合,一个用于结果,另一个用于问题。结果基本上是人们解决问题的地方,所以如果我没记错的话,它可以有 1 个问题或最多 99 个问题。这是简化的架构:

Results Schema:
_id: ObjectId("6010664ac5c4f77f26f5d005")
questions: [
  {
    _id: ObjectId("5d2627c94bb703bfcc910763"),
    correct: false
  },
  {
    _id: ObjectId("5d2627c94bb703bfcc910764"),
    correct: true
  },
  {
    _id: ObjectId("5d2627c94bb703bfcc910765"),
    correct: true
  }
]

所以,对于这个特定的对象,用户回答了 3 个问题,其中 2 个是正确的。

Questions Schema:
_id: ObjectId("5d2627c94bb703bfcc910763")

我正在努力做的是:对于所有问题架构中的每个元素,我必须检查问题是否得到回答 - 即(检查问题架构上是否有问题数组的 _id == _id,是的可以有多个问题与 Questions Schema 具有相同的 _id,但 Questions Schema _id 是唯一的)。如果该问题得到了回答,我需要检查是否正确=真,如果是,我将其添加到一个正确答案变量中,如果不是,则为错误答案。

到目前为止,我已经尝试了很多条件,分组以获得正确和错误答案的 $sum,查找以加入两个集合,但到目前为止,我什至无法只显示聚合结果。

我尝试过的其中一件事(我试图先做一些小步骤)但如前所述,甚至无法打印结果。

Result.aggregate([
    $lookup: {
      from: 'question',
      localField: 'questions._id',
      foreignField: '_id',
      as: 'same'
    },

但这让我将两个集合结合在一起,并且“相同”作为空数组出现,尝试使用 match 也没有运气。 我还做了一个 $project 来获取我想要的信息

$project: {
  _id: 0,
  questions: {
  _id: 1,
  correct: 1
  }
},

尝试使用 $group: $组:{ _id: "$_id", $cond: {if: {"$correct": { $eq: true}}, then: {testField: {$sum: 1}}, else: {testField: 0}} } 正如我所说,我只是尝试做一些小步骤,所以 testField 是手动设置的,还尝试了 stackoverflow 中的许多其他事情。 非常感谢您的帮助,并为很长的文字感到抱歉,只是想举一些我做过并尝试过的例子。

TLDR:需要从Results Schema中找到一个question,其中_idQuestions Schema中的一个_id匹配,如果有,检查是correct: true还是@ 987654331@。相应地更新Questions Schema,从Questions Schema 中的每个question 有多少是正确的,多少是错误的。 示例:newField: {correctAnswer: 4, wrongAnswer: 3} 所以在这种情况下,Result schemaquestion 数组中有 7 个问题与来自Question Schema_id 匹配,4 个问题具有 correct: true,3 个问题具有 correct: false。然后在Question Schema的其余部分继续这样下去@

【问题讨论】:

  • 你能澄清一下你在找什么吗?是不是,对于每个question,您想要返回两个数组,一个数组带有_id 来自answer"correct": true 答案,另一个数组带有_id 来自answer"correct": false 答案?
  • 是的,对不起。文中没说,但是想更新Questions Schema添加一个属性说有多少问题是正确的,有多少问题是错误的,基本上是添加一个新字段newField: {correctAnswers: 2, wrongAnswers: 5}

标签: mongodb


【解决方案1】:

对于由于Question 集合位于不同数据库中而无法使用"$lookup" 的场景,Result 集合可用于生成输出文档以更新Question 集合。

这是一种方法。

db.Result.aggregate([
  {
    "$unwind": "$questions"
  },
  {
    "$group": {
      "_id": "$questions._id",
      "correct": {
        "$push": "$questions.correct"
      }
    }
  },
  {
    "$project": {
      "newField": {
        "correctAnswers": {
          "$size": {
            "$filter": {
              "input": "$correct",
              "as": "bool",
              "cond": "$$bool"
            }
          }
        },
        "wrongAnswers": {
          "$size": {
            "$filter": {
              "input": "$correct",
              "as": "bool",
              "cond": { "$not": "$$bool" }
            }
          }
        }
      }
    }
  }
])

试试mongoplayground.net

【讨论】:

  • 我不能投票,所以我只会发表评论。效果很好,非常感谢您抽出宝贵的时间!我被困住了 1 周
  • 很高兴它成功了!如果它满足您的需求,您可以“接受”答案。顺便说一句,我有自己的 MongoDB 查询需要开发,但是通过尝试解决 SO 上出现的问题,我对 MongoDB 的工作知识得到了极大的扩展。感谢您的挑战!
  • 很高兴听到这个消息。我还想知道,如果我想得到这些答案的最后 7 天,这些答案基于 createdAt 字段,位于问题数组之外,与_id 在同一个巢穴中,我会怎么做。我试图只投影createdAt 字段但没有得到任何运气:(
  • @DAVIFONSECA 您可以根据自己的条件使用"$match" 作为管道的第一阶段。
【解决方案2】:

我不知道有什么方法可以同时使用"$lookup"update。可能有更好的方法来做到这一点,但下面的聚合管道创建了可以在后续update 中使用的文档。管道通过单个 Result _id 正确计算重复问题,以防有人一直尝试问题直到他们做对为止。一个可能的问题是,如果问题没有 Result 答案,则不会创建 "newField": { "correctAnswers": 0, "wrongAnswers": 0 } 文档。

db.Question.aggregate([
  {
    // lookup documents in Result that match _id
    "$lookup": {
      "from": "Result",
      "localField": "_id",
      "foreignField": "questions._id",
      "as": "results"
    }
  },
  {
    // unwind everything
    "$unwind": "$results"
  },
  {
    // more of everything
    "$unwind": "$results.questions"
  },
  {
    // only keep answers that match question
    "$match": {
      "$expr": { "$eq": [ "$_id", "$results.questions._id" ] }
    }
  },
  {
    // reassemble and count correct/wrong answers
    "$group": {
      "_id": "$_id",
      "correct": {
        "$sum": {
          "$cond": [ { "$eq": [ "$results.questions.correct", true ] }, 1, 0 ]
        }
      },
      "wrong": {
        "$sum": {
          "$cond": [ { "$eq": [ "$results.questions.correct", false ] }, 1, 0 ]
        }
      }
    }
  },
  {
    // project what you want as output
    "$project": {
      newField: {
        correctAnswers: "$correct",
        wrongAnswers: "$wrong"
      }
    }
  }
])

试试mongoplayground.net

【讨论】:

  • 我尝试了我的代码,但它不起作用,但我知道可能是什么。我的 Result 集合在另一个数据库上,与 Question 不同。在这种情况下仍然可以进行查找吗?非常感谢您的回复!
  • 不幸的是,"$lookup" only works with an "unsharded collection in the same database"。您可以将集合移动到同一个数据库吗?如果没有,您可能会卡在从应用程序/编程端进行查找。另一种选择可能是“假装”Question 集合不存在,但由Result "questions._id" 表示。可以生成相同的输出文档。如果时间允许,我会用这种方法提交另一个答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-31
  • 2013-04-28
  • 1970-01-01
  • 2014-05-27
  • 1970-01-01
相关资源
最近更新 更多