#mongodb #mongodb-query #aggregation-framework
#mongodb #mongodb-запрос #агрегация-фреймворк
Вопрос:
У меня есть следующий $lookup
этап агрегации:
{
$lookup: {
from: "target",
let: {byTargetId: "$foreignTargetId"},
pipeline: [
{
$match: {
$expr: {
$eq: ["$targetId", "$byTargetId"]
}
}
},
{
$project: {
someTargetProperty: true
}
}
],
as: "targets"
}
}
В моей тестовой базе данных этап перед этим возвращает только 5 документов. В этом случае ни один из них не имеет необязательного свойства foreignTargetId
, поэтому я ожидаю byTargetId
, что будет undefined
каждый раз, и ни один документ в target
коллекции не будет совпадать.
Дело в том, что агрегация занимает на 1 секунду больше времени, если я добавлю этот этап поиска (в конце).
Если я выполню эту агрегацию для target
коллекции, которая идентична конвейеру поиска со undefined
значением для byTargetId
:
db.getCollection('target').aggregate(
[
{
$match: {
$expr: {
$eq: ["$targetId", undefined]
}
}
},
{
$project: {
someTargetProperty: true
}
}
])
тогда действительно это занимает около 200 мс, а 5×200 мс = 1 с, так что это имеет смысл.
Тем не менее, если я выполню ту же агрегацию со null
значением для byTargetId
:
db.getCollection('target').aggregate(
[
{
$match: {
$expr: {
$eq: ["$targetId", null]
}
}
},
{
$project: {
someTargetProperty: true
}
}
])
затем это выполняется за <1 мс.
- Чем вызвана такая большая разница между равенством совпадений на
null
иundefined
? - Как я могу пропустить этап $lookup, если
foreignTargetId
он отсутствует во входном документе для этого этапа?
Кстати, причина, по которой я использую конвейер поиска здесь, заключается в том, что документы в target
нем довольно большие, и мне нужно только someTargetProperty
то, что также находится в индексе, поэтому поиск может быть выполнен полностью в памяти. В других случаях я заметил, что это может быть значительно быстрее, чем просмотр всего документа и последующее проектирование. Я не буду принимать ответы, которые пытаются обойти эту проблему, не используя $lookup с конвейером.