MongoDB > 从嵌套数组中提取集合

3

我尝试了SO上找到的所有方法,但都没有成功。在MongoDB中完成一个看似简单的任务(例如使用json / lodash非常容易)。

我有一个集合:

db.users >

[
    {
        _id: 'userid',
        profile: {
            username: 'abc',
            tests: [
                {
                    _id: 'testid',
                    meta: {
                        category: 'math',
                        date: '9/2/2017',
                        ...
                    }
                    questions: [
                        {
                            type: 'add',
                            correct: true,
                        },
                        {
                            type: 'subtract',
                            correct: true,
                        },
                        {
                            type: 'add',
                            correct: false,
                        },
                        {
                            type: 'multiply',
                            correct: false,
                        },

                    ]
                },
                ...
            ]
        }
    },
    ...
]

我希望最终得到一个按问题类型分组的数组:
[
    {
        type: 'add',
        correct: 5,
        wrong: 3,
    },
    {
        type: 'subtract',
        correct: 4,
        wrong: 9
    }
    ...
]

我尝试过不同的聚合方式,最后一个是:

db.users.aggregate([
    { $match: { 'profile.tests.meta.category': 'math' }},
    { 
        $project: {
            tests: {
               $filter: {
                  input: "$profile.tests",
                  as: "test",
                  cond: { $eq: ['$$test.meta.category', 'math'] }
               }
            }
         }
    },
    { 
        $project: {
            question: "$tests.questions"
        }
    },
    { $unwind: "$questions"},

])

也尝试在管道末尾添加$group:

{
        $group:
        {
            _id: '$questions.type',
            res: {
                $addToSet: { correct: {$eq:['$questions.chosenAnswer', '$questions.answers.correct'] }
            }
        }
    }

没有任何变化能够给我我想要的东西,我肯定是缺少核心概念,我查看了文档但还是搞不清楚.. 基本上我正在寻找一个flatMap函数,用它来提取所有用户的所有问题并按类型分组。
如果有人能引导我朝正确的方向前进,我将非常感激 :) 谢谢。(另外,我正在使用Meteor,所以任何查询都必须在Meteor mongo中有效)

抱歉,只复制了相关字段,但这是个错误,应该是meta>category>math而不仅仅是category。我会更新问题的内容,谢谢。 - undefined
1个回答

2
您可以在3.4版本中尝试以下聚合方法。
使用$filter过滤出符合条件的math类别,再使用$map来处理每个匹配类别中的questions数组,接着使用$reduce$concatArrays将所有匹配类别中的questions合并成一个单一的数组。
然后,对问题数组进行$unwind操作,并按type分组,使用$sum计算correctwrong的数量。
db.users.aggregate([
  {
    "$match": {
      "profile.tests.meta.category": "math"
    }
  },
  {
    "$project": {
      "questions": {
        "$reduce": {
          "input": {
            "$map": {
              "input": {
                "$filter": {
                  "input": "$profile.tests",
                  "as": "testf",
                  "cond": {
                    "$eq": [
                      "$$testf.meta.category",
                      "math"
                    ]
                  }
                }
              },
              "as": "testm",
              "in": "$$testm.questions"
            }
          },
          "initialValue": [],
          "in": {
            "$concatArrays": [
              "$$value",
              "$$this"
            ]
          }
        }
      }
    }
  },
  {
    "$unwind": "$questions"
  },
  {
    "$group": {
      "_id": "$questions.type",
      "correct": {
        "$sum": {
          "$cond": [
            {
              "$eq": [
                "$questions.correct",
                true
              ]
            },
            1,
            0
          ]
        }
      },
      "wrong": {
        "$sum": {
          "$cond": [
            {
              "$eq": [
                "$questions.correct",
                false
              ]
            },
            1,
            0
          ]
        }
      }
    }
  }
])

1
你真的让我开心起来了..谢谢你花时间做这件事。 - undefined
我对MongoDB还不熟悉,正在努力理解你的操作,一定会深入研究$reduce:),在测试时,这个查询似乎运行得相当快,你有什么进一步优化的建议吗?我知道应该创建索引,这在这里是否相关?有人告诉我要将所有问题提取到它们自己的集合中...在这种情况下,您是否建议这样做...或者它们现在的位置很好?谢谢。 - undefined
Np. 你只能在$match阶段使用索引。所以为profile.tests.meta.category添加索引。在选择之前,你必须测试所有的选项。我还会尝试将问题移动到顶层,并放入自己的数组中,带有相关的元数据,以便将其与关联的测试联系起来(实质上是复制一些数据)。如果需要的话,现在也可以为问题添加$match。将此选项与当前结构和将其移动到自己的集合进行比较。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接