1

Я пытаюсь объединить два вложенных массива (используя $ concatArrays) в одно новое поле. Я хотел бы сортировать вывод конкатенации (Model.timeline) с помощью свойства, которое существует в обоих наборах объектов. Кажется, я не могу заставить его работать с $ unwind. Вот запрос без сортировки:

Model.aggregate([ 
    { 
     $match: { 
      'id': id 
     } 
    }, 
    { 
     $project: { 
      id: 1, 
      name: 1, 
      flagged: 1, 
      updatedAt: 1, 
      lastEvent: { 
       $arrayElemAt: ['$events', -1] 
      }, 
      lastimage: { 
       $arrayElemAt: ['$images', -1] 
      }, 
      timeline: { 
       $concatArrays: [ 
        { $filter: { 
         input: '$events', 
         as: 'event', 
         cond: { $and: [ 
          { $gte: ['$$event.timestamp', startAt] }, 
          { $lte: ['$$event.timestamp', endAt] } 
         ]} 
        }}, 
        { $filter: { 
         input: '$images', 
         as: 'image', 
         cond: { $and: [ 
          { $gte: ['$$image.timestamp', startAt] }, 
          { $lte: ['$$image.timestamp', endAt] } 
         ]} 
        }} 
       ] 
      } 
     } 
    } 
]); 

Я пропустил что-то очевидное?

ответ

0

Вам необходимо три этапа трубопровода после вашего матча и проекта. Сначала $unwind, затем $sort, а затем повторно $group. Используйте оператор $first, чтобы сохранить все поля.

{ 
    $undwind : "$timeline", 
}, 
{ 
    $sort : {"your.sortable.field" : 1} 
}, 
{ 
    $group : { 
     _id : "$_id", 
     name : {$first : 1}, 
     flagged : {$first : 1}, 
     updatedAt : {$first : 1}, 
     lastEvent : {$first : 1}, 
     lastimage : {$first : 1}, 
     timeline : {$push : "$timeline"} 
    } 
} 

Обратите внимание, что это будет работать, даже если у вас есть несколько документов после фазы соответствия. Таким образом, в основном это сортирует элементы массива внутри каждого документа.

0

Ваш $ матч и $ проекта стадии агрегации работал после того, как я заменял id с _id и заполнены значениями для id, startAt и endAt так:

db.items.aggregate([ 
    { 
     $match: { 
      '_id': '58' 
     } 
    }, 
    { 
     $project: { 
      '_id': 1, 
      name: 1, 
      flagged: 1, 
      updatedAt: 1, 
      lastEvent: { 
       $arrayElemAt: ['$events', -1] 
      }, 
      lastimage: { 
       $arrayElemAt: ['$images', -1] 
      }, 
      timeline: { 
       $concatArrays: [ 
        { $filter: { 
         input: '$events', 
         as: 'event', 
         cond: { $and: [ 
          { $gte: ['$$event.timestamp', ISODate("2016-01-19T20:15:31Z")] }, 
          { $lte: ['$$event.timestamp', ISODate("2016-12-01T20:15:31Z")] } 
         ]} 
        }}, 
        { $filter: { 
         input: '$images', 
         as: 'image', 
         cond: { $and: [ 
          { $gte: ['$$image.timestamp', ISODate("2016-01-19T20:15:31Z")] }, 
          { $lte: ['$$image.timestamp', ISODate("2016-12-01T20:15:31Z")] } 
         ]} 
        }} 
       ] 
      } 
     } 
    } 
]);