$ lookup не будет использовать индексы во втором $ match. Как мы можем масштабировать? - PullRequest
1 голос
/ 19 января 2020

В 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, что снова делает запрос медленным.

Есть ли способ обойти это ограничение?

1 Ответ

2 голосов
/ 19 января 2020

Невозможно обойти это ограничение, если вы опубликуете агрегацию, я могу попытаться сделать ее более эффективной.

«Реляционные» зависимости не подходят для неструктурированных баз данных, таких как Mon go Как правило, для повышения производительности запросов рекомендуется использовать дубликаты данных, что означает добавление поля category к ProductsShops. Это кажется «неправильным», если вы привыкли к структурированным БД, но здесь, с понедельника go, это не только не будет осуждено, но и рекомендуется.

Что нужно учитывать при этом, что вы жертвуете «целостностью», то есть, когда вы обновляете категорию продуктов, ее синхронизация с другой коллекцией не будет очевидной c, очевидно, с учетом сказанного я предполагаю, что действие происходит не часто, поскольку продукты не получают новые категории каждый день.

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