首页 > 解决方案 > 查找和排序外国集合

问题描述

所以我有一个集合users,这个集合中的每个文档以及其他属性都有另一个集合中文档的 ids 数组:workouts. 集合中的每个文档workouts都有一个名为 的属性date

这就是我想要得到的:

对于特定用户,我想获取属于该用户的锻炼的 {workoutId,锻炼日期} 数组,按日期排序。

这是我的尝试,效果很好。

Users.aggregate([
    { 
        $match : {
            _id : ObjectId("whateverTheUserIdIs")
        }
    }, 
    { 
        $unwind : {
            path : "$workouts"
        }
    }, { 
        $lookup : {
            from : "workouts", 
            localField : "workouts", 
            foreignField : "_id", 
            as : "workoutDocumentsArray"
        }
    }, { 
        $project : {
            _id : false, 
            workoutData : {
                $arrayElemAt : [
                    $workoutDocumentsArray, 
                    0
                ]
            }
        }
    }, { 
        $project : {
            date : "$workoutData.date", 
            id : "$workoutData._id"
        }
    }, { 
        $sort : {date : -1}
    }
])

但是,我拒绝相信我需要所有这些才能在 SQL 中进行如此简单的查询!?我相信我至少必须能够将两个$project阶段合二为一?但我无法弄清楚如何查看文档。

提前感谢您抽出宝贵时间!;)

==== 编辑 - 这是一些示例数据

收藏用户:

[{
  _id:xxx,
  workouts: [2,4,6]
 },{
  _id: yyy,
  workouts: [1,3,5]
}]

集体训练:

[{
  _id:1,
  date: 1/1/1901
 },{
  _id:2,
  date: 2/2/1902
 },{
  _id:3,
  date: 3/3/1903
 },{
  _id:4,
  date: 4/4/1904
 },{
  _id:5,
  date: 5/5/1905
 },{
  _id:6,
  date: 6/6/1906
 }]

在运行我的查询后,例如对于用户 xxx,我只想获取属于他的锻炼(其 id 出现在他的锻炼数组中),所以我想要的结果如下所示:

[{
  id:6,
  date: 6/6/1906
 },{
  id:4,
  date: 4/4/1904
 },{
  id:2,
  date: 2/2/1902
 }]

标签: mongodboptimizationmongodb-querynosqlaggregation-framework

解决方案


您不需要数组$unwindworkouts因为它已经包含_ids 数组并使用$replaceRoot而不是做$project

Users.aggregate([
  { "$match": { "_id" : ObjectId("whateverTheUserIdIs") }}, 
  { "$lookup": {
    "from" : "workouts", 
    "localField" : "workouts", 
    "foreignField" : "_id", 
    "as" : "workoutDocumentsArray"
  }},
  { "$unwind": "$workoutDocumentsArray" },
  { "$replaceRoot": { "newRoot": "$workoutDocumentsArray" }}
  { "$sort" : { "date" : -1 }}
])

甚至使用新$lookup语法

Users.aggregate([
  { "$match" : { "_id": ObjectId("whateverTheUserIdIs") }}, 
  { "$lookup" : {
    "from" : "workouts", 
    "let": { "workouts": "$workouts" },
    "pipeline": [
      { "$match": { "$expr": { "$in": ["$_id", "$$workouts"] }}},
      { "$sort" : { "date" : -1 }}
    ]
    "as" : "workoutDocumentsArray"
  }},
  { "$unwind": "$workoutDocumentsArray" },
  { "$replaceRoot": { "newRoot": "$workoutDocumentsArray" }}
])

推荐阅读