В MongoDB 3.6 у нас есть коллекция Products
, которая на данный момент имеет 150 тыс. Документов, и нам нужно хранить для каждого продукта его цену за магазин. На данный момент насчитывается около 1000 магазинов.
Наша стратегия состоит в том, чтобы создать вторую коллекцию, назовем ее ProductShops
:
{
_id: "product_shop_id_1",
productId: "product_id_1",
shopId: "shop_id_1",
price: 15,
stock: 3,
enabled: true
}
Так как нам нужно выполнять запросы с использованием фильтров в обеих коллекциях Например, выбрать товары, которые есть на складе в магазине X и принадлежат к категории Y (категория товара хранится в коллекции Products
), мы сделаем запрос агрегации в коллекцию товаров, отфильтруем результаты, затем перейдем к ProductShops
collection, затем отфильтруйте результаты снова.
Конвейер агрегирования выглядит следующим образом:
[
match,
sort,
lookup,
unwind,
match,
project,
skip,
limit
]
Проблема, однако, заключается в том, что, как указано в документации mongodb, второе совпадение будет не используйте индексы, что делает поиск бесполезным при работе с миллионами документов, и возникает запрос на сканирование всей коллекции (например, когда результаты меньше предела). Мы протестировали его, и в нашем текущем размере данных это может занять до 30 секунд.
Мы попытались использовать новый синтаксис $lookup
, который учитывает встроенный конвейер и выполняет там фильтрацию, которая, кажется, работает быстрее, но это не отфильтрует продукт, который соответствует нулю ProductShops
документов. Таким образом, нам все еще нужно отфильтровать их на более позднем этапе, используя $match
или $unwind
с preserveNullAndEmptyArrays : false
, что снова делает запрос медленным.
Есть ли способ обойти это ограничение?