• Как указать несколько пар условий в запросе по списку?

    @Asapin
    В свободное время ковыряюсь с Rust и Wasm
    Про хешированные индексы
    Судя по документации, MongoDB не поддерживает хешированные индексы для массивов.
    Хешированные индексы нужны для того, что бы более равномерно распределить данные, которые расположены близко к друг другу. Их часто применяют при шардировании коллекций (когда одна коллекция разбита на несколько частей, которые хранятся на разных серверах). В таком случае, запросы на выбор этих данных не будут идти всегда на один и тот же сервер. Но если у вас запросы вида поле1 > значение1 && поле1 < значение2, то индекс использоваться не будет (потому что в таком случае монге надо будет сгенерировать все возможные промежуточные значения и посчитать для них хеши, что невозможно).

    Но судя по документации, хешированные индексы также можно применять и для embedded-документов (сам так не делал), но подозреваю, что в таком случае в запросе надо передавать весь embedded-документ, что бы для него правильно посчитался хеш.

    Про индексы в целом
    В целом, задача индекса в том, что бы после первичного поиска по нему осталось как можно меньше документов для последующего перебора, поэтому рекомендуется строить индекс по полям, которые у вас гарантированно участвуют в каждом запросе.
    Скажем, у вас в коллекции проиндексированно только поле username и вы выполняете свой запрос вида
    $or: [
    ["username" : "user1", tags: "tag4"],
    ["username" : "user2", tags: "tag1"],
    ["username" : "user2", tags: "tag3"],
    ]

    в таком случае, MongoDB с помощью индекса очень быстро выберет все документы, у которых username равен либо user1, либо user2, а затем уже начнёт перебирать найденные документы и проверять их на совпадение остальным параметрам запроса.

    Получается, лучше делать составной индекс username + tags?
    Не всегда. При использовании в индексе поля типа Array, на каждый элемент массива будет создана отдельная запись в индексе.
    Если у вас мало документов, у которых поле username имеет одинаковое значение, но при этом в массиве tags может быть много значений, и значения внутри одного массива могут повторяться, то использование составного индекса приведёт к большему количеству одинаковых записей в индексе, чем если бы вы использовали индексацию только по полю username.

    Отсюда же вытекает другое ограничение: в составном индексе только одно из полей может быть массивом, иначе в индексе на каждый документ пришлось бы создавать N ・ M записей, где N и M - размеры массивов, которые участвуют в построении индекса.

    Отдельное поле с хешем
    В таком случае, вам при каждом редактировании документа надо будет загружать полный документ из базы, обновлять его, вычислять вручную новый хеш и сохранять документ обратно. А значит вы не сможете использовать запросы, которые обновляют только отдельные поля, например прямое редактирование массива.

    Отдельная коллекция с хешами
    Транзакционность в MongoDB есть только на уровне отдельного документа. А это значит, что вам придётся самому следить за консистентностью данных в обеих коллекциях, что может обернуться той ещё головной болью: что вы будете делать, если документ был отредактирован, но информация в связанной коллекции по каким-то причинам не была обновлена (например, прервалась связь с БД или приложение упало из-за нехватки памяти)? Поэтому лично я в общем случае такой подход не рекомендовал бы.

    Так что же делать?
    Самое простое и эффективное, что вы можете сделать - поднять монгу локально, сгенерировать в ней реалистичные данные, поиграться с разными настройками индексов и замерить скорость выполнения запросов.
    Дополнительно можете воспользоваться методом explain, что бы посмотреть статистику выполнения запроса.
    Ответ написан
    Комментировать