В качестве примера возьмем следующие данные:
{
_id: 1,
item: "abc",
stock: [
{ size: "S", color: "red", quantity: 25 },
{ size: "S", color: "blue", quantity: 10 },
{ size: "M", color: "blue", quantity: 50 }
]
}
{
_id: 2,
item: "def",
stock: [
{ size: "S", color: "blue", quantity: 20 },
{ size: "M", color: "blue", quantity: 5 },
{ size: "M", color: "black", quantity: 10 },
{ size: "L", color: "red", quantity: 2 }
]
}
{
_id: 3,
item: "ijk",
stock: [
{ size: "M", color: "blue", quantity: 15 },
{ size: "L", color: "blue", quantity: 100 },
{ size: "L", color: "red", quantity: 25 }
]
}
Скажем, я собираюсь отфильтровать stock
s, которые соответствуют критериям size = 'L'
. У меня уже есть индекс мультиключа в поле stock.size
.
В конвейере агрегации, если я использую следующие две операции:
[{$unwind: {path: "$stock"}},
{$match: {"stock.size": "L"}}]
Я получу желаемые результаты, но когда база данных станет очень большой, на шаге $unwind
придется сканировать всю коллекцию без использования существующего индекса, что очень неэффективно.
Если я переверну порядок операций $unwind
и $match
, $match
будет использовать индекс для применения ранней фильтрации, но конечный результат будет не таким, как хотелось бы: он получит дополнительные stock
s, которые не имеют размер L, но имеют родного размера stock
s, которые принадлежат тем же item
.
Должен ли я использовать одну и ту же операцию $match
дважды, т. Е. Как до, так и после $unwind
, чтобы она использовала индекс и возвращала правильные результаты?