Поиск и сортировка иностранной коллекции - PullRequest
0 голосов
/ 09 октября 2018

, поэтому у меня есть коллекция users, и каждый документ в этой коллекции, а также другие свойства имеют массив идентификаторов документов в другой коллекции: workouts.Каждый документ в коллекции workouts имеет свойство с именем date.

И вот что я хочу получить:

Для конкретного пользователя я хочу получить массивиз {workoutId, workoutDate} для тренировок, принадлежащих этому пользователю, отсортированных по дате.

Это моя попытка, которая работает нормально.

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

Ипосле выполнения моего запроса, например, для пользователя ххх, я хотел бы получить только те тренировки, которые ему принадлежат (чьи идентификаторы появляются в его массиве тренировок), поэтому желаемый результат будет выглядеть следующим образом:

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

1 Ответ

0 голосов
/ 09 октября 2018

Вам не нужно $unwind массив workouts, поскольку он уже содержит массив _id s и использовать $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" }}
])
...