Lookup and sort the foreign collection

删除回忆录丶 提交于 2020-03-03 10:25:13

问题


so I have a collection users, and each document in this collection, as well as other properties, has an array of ids of documents in the other collection: workouts. Every document in the collection workouts has a property named date.

And here's what I want to get:

For a specific user, I want to get an array of {workoutId, workoutDate} for the workouts that belong to that user, sorted by date.

This is my attempt, which is working fine.

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

However I refuse to believe I need all this for what would be such a simple query in SQL!? I believe I must at least be able to merge the two $project stages into one? But I've not been able to figure out how looking at the docs.

Thanks in advance for taking the time! ;)

==== EDIT - This is some sample data

Collection users:

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

Colleciton workouts:

[{
  _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
 }]

And after running my query, for example for user xxx, I would like to get only the workouts that belong to him (whose ids appear in his workouts array), so the result I want would look like:

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

回答1:


You don't need to $unwind the workouts array as it already contains array of _ids and use $replaceRoot instead of doing $project

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

or even with new $lookup syntax

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


来源:https://stackoverflow.com/questions/52720716/lookup-and-sort-the-foreign-collection

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!