Создайте новое поле с логическим значением, основанным на том, находится ли значение данного документа в массиве - PullRequest
1 голос
/ 11 октября 2019

Учитывая, что у меня есть массив идентификаторов, например:

db.calendars.aggregate([
   { '$match' : { _id: { '$in' : filtered_ids } }  },
   { '$group' : { _id: null, ids: { '$push' : '$_id' }  }  },
   { '$project' : {_id: 0, ids: 1} }
])
{ "ids" : [ ObjectId("5d9ce5d73ed1492058a3a2df"), ObjectId("5d9ce88e3ed14921b6e1a9f1"), ObjectId("5d9ce88e3ed14921b6e1a9f3") ] }

Я хочу создать новое поле в приведенном ниже конвейере агрегации, которое оценивается как 1 или -1, если данный идентификатор документа существует илине в приведенном выше массиве идентификаторов. По сути, я смогу отсортировать документы по логическому значению. Сначала кажется, что подходит оператор '$cmp'.

db.calendars.aggregate([
  { '$addFields' : { 'shared' : { '$cmp' : ['$_id', [ ObjectId("5d9ce5d73ed1492058a3a2df"), ObjectId("5d9ce88e3ed14921b6e1a9f1"), ObjectId("5d9ce88e3ed14921b6e1a9f3") ] ] } },
  { '$sort' : { shared: -1 }  }
])

Но оператор '$ cmp' сравнил только два значения. Он не делает то, что делает $ in, чтобы сравнить, находится ли одно значение в массиве значений. Мой вопрос заключается в том, как я могу включить требование $ in при сравнении значений.

Ожидаемый результат будет выглядеть следующим образом:

{ '_id' : Object('...'), name: 'New event', shared: -1 },
{ '_id' : Object('...'), name: 'Another event', shared: -1 },
{ '_id' : Object('...'), name: 'Cool event', shared: 1 },
{ '_id' : Object('...'), name: 'Wow, an event', shared: 1 },

Вы видите, как документы сортируются по этомуновое поле?

1 Ответ

0 голосов
/ 11 октября 2019

$ in возвращает логическое значение, поэтому вы можете использовать $ cond для установки 1 или -1:

db.calendars.aggregate([
    {
        $addFields: {
            shared: {
                $cond: [ { $in: [ "$_id", [ ObjectId("5d9ce5d73ed1492058a3a2df"), ObjectId("5d9ce88e3ed14921b6e1a9f1"), ObjectId("5d9ce88e3ed14921b6e1a9f3") ] ] }, 1, -1 ]
            }
        }
    },
    { '$sort' : { shared: -1 }  }
])

или для запуска $sort на логическое значение, если вы хотите упростить:

db.calendars.aggregate([
    {
        $addFields: {
            shared: {
                $in: [ "$_id", [ ObjectId("5d9ce5d73ed1492058a3a2df"), ObjectId("5d9ce88e3ed14921b6e1a9f1"), ObjectId("5d9ce88e3ed14921b6e1a9f3") ] ] 
            }
        }
    },
    { '$sort' : { shared: -1 }  }
])
...