首页 > 解决方案 > MongoDB查询多个子文档

问题描述

我的 MongoDB 数据结构如下所示:

{
  users: [{
    userref: "User1",
    results: [{
      testref: "TEST1",
      history: [{
        score: 10
      }, {
        score: 15
      }]
    }, {
      testref: "TEST2",
      history: [{
        score: 2
      }, {
        score: 1
      }]
    }]
  }]
}

我有一组用户,每个用户都有一组结果(每个测试一个结果对象),并且在每个结果中,都有一组历史分数的历史记录。

我需要做的是“返回 TEST1 的最新分数为 X 且 TEST2 的最新分数为 Y 的所有用户的 userref”。未完成其中一项或多项测试的用户不应被退回。“最近的”是指数组中的最后一个。

我假设我需要使用聚合,但我对此完全陌生,所以可以通过一些帮助来做。

这是我迄今为止尝试过的,它有效,但它只匹配TEST1 = 15的条件,我也希望它匹配条件TEST2 = 1。

[{$unwind: {
  path: '$results’,
  preserveNullAndEmptyArrays: false
}}, {$match: {
  'results.testref': 'TEST1'
}}, {$project: {
  results: 1,
  userref: 1,
}}, {$replaceRoot: {
  newRoot: {
    $mergeObjects: [
      {
        userref: '$userref'
      },
      '$results'
    ]
  }
}}, {$project: {
  userref: 1,
  history: {
    $slice: [
      '$history',
      -1
    ]
  }
}}, {$match: {
  'history.score': 15
}}, {$project: {
  userref: 1,
}}]

谢谢

标签: mongodbaggregation-framework

解决方案


要同时满足这两个条件,

db.getCollection('test2').aggregate([{"$unwind":"$users"}, {$unwind:"$users.results"}, 
{$project:
     {"lastScore": 
        {$slice:
            ["$users.results.history", -1]
        },
     "users.userref":1,
     "users.results.testref":1
    }
},
{
    $match:{"$or":[{
      $and:[
        {"users.results.testref":"TEST1"},
        {"lastScore.0.score":15}
      ]},
      {
      $and:[
        {"users.results.testref":"TEST2"},
        {"lastScore.0.score":1}
      ]}
      ]
    }
},
{
    $group:{
        "_id":{"_id":"$_id","userref":"$users.userref"},
        "data":{$push:{"tests":"$users.results.testref", "userref":"$users.userref"}}
    }
},
{
    $project:{
        "_id":1,
        "validUser":{
        "$filter":{
            "input":"$data",
            "as":"data",
            "cond":{$or:[{$eq:["$$data.tests","TEST1"]}, {$eq:["$$data.tests","TEST2"]}]}
        }}
    }
},
{
    $project:{
        "_id.userref":1
    }
}
])

查询有什么作用:

  1. 放松用户
  2. 放松结果
  3. 获取最后分数部分以及用户参考,测试参考
  4. 检查必要条件
  5. 将用户 ref 和 doc id 重新分组
  6. 使用 $filte 检查两个条件是否满足
  7. 项目用户参考

输出:

/* 1 */
{
    "_id" : {
        "userref" : "User1"
    }
}

推荐阅读