查找并排序外国馆藏

时间:2018-10-09 12:08:04

标签: mongodb optimization nosql aggregation-framework aggregation

所以我有一个集合users,该集合中的每个文档以及其他属性在另一个集合workouts中都有一个文档ID数组。 集合workouts中的每个文档都有一个名为date的属性。

这就是我想要得到的:

  

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

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

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

1 个答案:

答案 0 :(得分:1)

您无需$unwindworkouts数组,因为它已经包含_id个数组,并且可以使用$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" }}
])