Поиск с использованием массива идентификаторов с конвейером - PullRequest
1 голос
/ 23 мая 2019

Я пытался написать функцию поиска, которая принимает массив с идентификаторами объектов и временными метками объекта y.Это сработало безупречно с localflied и foreignfield, но я не могу воспроизвести тот же результат с использованием конвейера.

(имена, подобные y, составлены так, чтобы оно было общим)

Рабочая версия:

$lookup: {
   from: 'y',
   localField: 'ys.object_id',
   foreignField: '_id',
   as: 'docs',
},

ys - это массив объектов, структурированных так:

{
  object_id: ObjectID(),
  timestamp: Date(),
}

Я хотел бы переписать это выражение, чтобы использовать конвейер, потому что я уже хочу отфильтровать некоторые объектыпосмотрел, используя их атрибут timestamp.

То, что я пробовал:

$lookup: {
   from: 'y',
   let: { ys: '$ys' },
   pipeline: [
     {
       $match: { $expr: { $eq: ['$_id', '$$ys.object_id'] } },
     },
   ],
   as: 'docs',
},

Размер базы данных: 20.4GB

Полный запрос:

const query = [
  {
    $match: { 'ys.timestamp': { $lte: date, $gt: previousMonth } },  // I have shorten this part a little (It's not the same but the logic was flawed anyway)
  },
  {
    $limit: 100,
  },
  {
    $lookup: {
      from: 'y',
      let: { ys: '$ys' },
      pipeline: [
        {
          $match: { $expr: { $in: ['$_id', '$$ys.object_id'] } },
        },
        {
          $sort: { timestamp: -1 },
        },
        {
          $limit: 1,
        },
      ],
      as: 'doc',
    },
  },
];

Приведенное выше решение не работает, похоже, застревает и никогда ничего не возвращает.(Время истекает через некоторое время)

Существует ли правильный способ переписать рабочее решение в конвейерное решение?

ВАЖНО : Я изменил запрос для поискаодин конкретный элемент по идентификатору, а затем выполнить поиск.Это действие сработало, но заняло около 20 секунд.Я вполне уверен, что именно поэтому мой запрос истекает, когда я запускаю его с моим обычным запросом.Кто-нибудь может объяснить, почему существует разница в производительности между этими двумя подходами, и если я могу как-то обойти это?

1 Ответ

0 голосов
/ 23 мая 2019

Очень близко - используйте $in вместо $eq:

$lookup: {
   from: 'y',
   let: { ys: '$ys' },
   pipeline: [
     {
       $match: { $expr: { $in: ['$_id', '$$ys.object_id'] } },
     },
   ],
   as: 'docs',
},

Если вы используете $eq, вы ищете значение, равное этому массиву. Использование $in означает, что вы ищете значение, которое содержится в этом массиве (например, includes).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...