Искать документы и возвращать только недостающие значения - PullRequest
2 голосов
/ 13 июля 2020

У меня есть 2 такие коллекции, A коллекция документов 1,5kk:

A
_id
relation: { alias, ref: 'B/<_id>' }

B
_id
name

Я хочу запросить элементы в A, которых нет в B. Вот что я получил до сих пор:

db.getCollection('A').aggregate([
    {
        $project: {
            'relation.ref': {
                $arrayElemAt: [
                    { $split: ['$relation.ref', '/'] }, 1
                ]
            },
            a: "$$ROOT"
        }
    },
    {
        $lookup: {
            from: 'B',
            localField: 'relation.ref',
            foreignField: '_id',
            as: 'b'
        }
    }
]);

Это действительно возвращает вещи в этом шаблоне:

{
  _id,
  relation.ref,
  a: {},
  b: [{}]
}

Ну, я ожидал добавить предложение $ match, чтобы включить только те, которые b - пустой массив. Что-то вроде ${match: { b: {$size: 0} } }

Проблема в том, что этот запрос занимает слишком много времени. Я никогда не видел, чтобы это работало, поэтому я не знаю, что это правильный путь.

Есть ли что-нибудь, что могло бы улучшить его работу, или другой способ добиться этого?

Например, если я заставлю неправильное соединение, он вернет пустой массив на b. Но запрос размера этого массива всегда выполняется медленно, даже когда я запрашиваю {$size: 1}, что составляет 99,9% результатов. Интересно, могу ли я сделать что-то вроде этого, чтобы выбрать только недостающие значения во время соединения:

{$lookup.pipeline: [{$myself: null}] }

Идеи, пожалуйста?

Спасибо

1 Ответ

1 голос
/ 13 июля 2020

Ваш синтаксис $match был близок, но немного не так, вы должны использовать что-то вроде этого:

{
    $match: {
      $expr: {
        $eq: [
          0,
          {
            $size: "$b"
          }
        ]
      }
    }
  }

MongoPlayground

Как бы то ни было проще обновить поле relation, чтобы оно содержало только действительные ссылки? и если это так, вы можете просто запросить 'relation.ref': {$exists: false}

...