简体   繁体   English

MongoDB 聚合不同 collections

[英]MongoDB aggregate different collections

i've been trying to do this aggregation since yesterday with no luck, hope you guys can give me some ideas.从昨天开始,我一直在尝试进行这种聚合,但没有成功,希望你们能给我一些想法。 A little background, I have 2 collections, one for results and another for questions.一点背景,我有 2 个 collections,一个用于结果,另一个用于问题。 Results is basically where people solve questions, so it can have 1 question or up to 99 if i'm not mistaken.结果基本上是人们解决问题的地方,所以如果我没记错的话,它可以有 1 个问题或最多 99 个问题。 This is the simplified schema:这是简化的架构:

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

So, on this specific object, the user answered 3 questions and got 2 of them correct.因此,对于这个特定的 object,用户回答了 3 个问题并答对了其中 2 个。

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

What i'm struggling to do is: for each element in all the questions schema, I have to check if the question was answered - ie (check if there's an _id of questions array == _id on the Questions Schema, yes there can be multiple questions with the same _id as Questions Schema, but Questions Schema _id is unique).我正在努力做的是:对于所有问题模式中的每个元素,我必须检查问题是否已得到回答 - 即(检查问题模式中是否有问题数组 == _id 的 _id,是的,可以_id 与 Questions Schema 相同的多个问题,但 Questions Schema _id 是唯一的)。 If that question was answered, I need to check if correct = true, if so, I add it to a correctAnswer variable, if not, wrongAnswer.如果回答了该问题,我需要检查是否正确 = 真,如果是,我将其添加到 correctAnswer 变量,如果不是,则添加 wrongAnswer。

I've tried many things so far with conditions, group to get the $sum of correct and wrong answers, lookup to join both collections but so far, I can't even get to show just the aggregation result.到目前为止,我已经尝试了很多有条件的事情,分组以获得正确和错误答案的 $sum,查找以加入 collections 但到目前为止,我什至无法只显示聚合结果。

One of the things I tried (i was trying to do baby steps first) but as mentioned before, couldn't even get the result printed.我尝试过的其中一件事(我试图先做婴儿步骤)但如前所述,甚至无法打印结果。

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

But this gets me both collections combined, and 'same' comes as empty array, tried using match with also no luck.但这让我得到了 collections 组合,并且“相同”作为空数组出现,尝试使用匹配也没有运气。 I also did a $project to just get the information I wanted我还做了一个 $project 来获取我想要的信息

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

Tried using $group: $group: { _id: "$_id", $cond: {if: {"$correct": { $eq: true}}, then: {testField: {$sum: 1}}, else: {testField: 0}} } And as I said, i was just trying to do baby steps so it the testField was beeing manually set, also tried many other things from stackoverflow.尝试使用 $group: $group: { _id: "$_id", $cond: {if: {"$correct": { $eq: true}}, then: {testField: {$sum: 1}}, else : {testField: 0}} } 正如我所说,我只是想做一些小步骤,所以 testField 是手动设置的,还尝试了 stackoverflow 中的许多其他东西。 Would appreciate the help and sorry for the very long text, just wanted to put in some examples that I did and tried.感谢您的帮助,对于很长的文字感到抱歉,只是想举一些我做过和尝试过的例子。

TLDR : Need to find a question from the Results Schema where _id matches an _id from the Questions Schema , if there is, check if correct: true or correct: false . TLDR :需要从Results Schema中找到一个question ,其中_idQuestions Schema中的_id匹配,如果有,请检查correct: truecorrect: false Update Questions Schema accordingly with how many were correct and how many were wrong for each question from Questions Schema .根据 Questions Schema 中的每个question ,相应地更新Questions Schema Questions Schema多少是正确的,有多少是错误的。 Example: newField: {correctAnswer: 4, wrongAnswer: 3} so in this case, there were 7 questions from the Result schema question array that matched an _id from Question Schema , 4 had correct: true and 3 had correct: false .示例: newField: {correctAnswer: 4, wrongAnswer: 3}所以在这种情况下, Result schema question数组中有 7 个问题与Question Schema中的_id匹配,4 个correct: true ,3 个correct: false Then it goes on like this for the rest of Question Schema然后对于Question Schema的 rest 这样继续下去

I don't know of a way to "$lookup" and update at the same time.我不知道同时"$lookup"update的方法。 There's probably a better way to do this, but the aggregation pipeline below creates the documents that could be used in a subsequent update .可能有更好的方法来执行此操作,但下面的聚合管道会创建可在后续update中使用的文档。 The pipeline correctly counts repeat questions by a single Result _id , in case someone keeps trying a question until they get it right.管道通过单个Result _id正确地计算重复问题,以防有人不断尝试一个问题直到他们做对为止。 One possible issue is that if a question has no Result answers, then no "newField": { "correctAnswers": 0, "wrongAnswers": 0 } document is created.一个可能的问题是,如果问题没有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"
      }
    }
  }
])

Try it on mongoplayground.net .mongoplayground.net上试用。

For a scenario where "$lookup" can't be used because the Question collection is in a different database, the Result collection may be used to generate output documents to update the Question collection.对于因为Question集合在不同的数据库中而无法使用"$lookup"的场景,可以使用Result集合生成output个文档来更新Question集合。

Here's one way to do it.这是一种方法。

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" }
            }
          }
        }
      }
    }
  }
])

Try it on mongoplayground.net .mongoplayground.net上试用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM