Сортировка по нескольким полям mongo DB
У меня есть запрос в mongo, так что я хочу отдать предпочтение первому полю, а затем второму полю.
Скажем, мне нужно запросить, чтобы
db.col.find({category: A}).sort({updated: -1, rating: -1}).limit(10).explain()
Итак, я создал следующий индекс
db.col.ensureIndex({category: 1, rating: -1, updated: -1})
Он работал только с оштрафованным сканированием как можно большего количества объектов, т.е. 10
Но теперь мне нужно запросить
db.col.find({category: { $ne: A}}).sort({updated: -1, rating: -1}).limit(10)
Итак, я создал следующий индекс
db.col.ensureIndex({rating: -1, updated: -1})
но это приводит к сканированию всего документа и при создании
db.col.ensureIndex({ updated: -1 ,rating: -1})
Он сканирует меньшее количество документов
Я просто хочу попросить четко рассказать о сортировке по нескольким полям и каков порядок сохранения при этом. Читая документы mongo-DB, ясно, что поле, в котором нам нужно выполнить сортировку, должно быть последним полем. Так вот в том, что я предположил в моем запросе $ne выше. Я делаю что-то неправильно?
Ответы
Ответ 1
Оптимизатор запросов MongoDB работает, пытаясь разным планам определить, какой подход лучше всего подходит для данного запроса. План выигрыша для этого шаблона запроса затем кэшируется для следующих ~ 1000 запросов или пока вы не выполните explain()
.
Чтобы понять, какие планы запросов были рассмотрены, вы должны использовать explain(1)
, например:
db.col.find({category:'A'}).sort({updated: -1}).explain(1)
Детали allPlans
будут отображать все планы, которые были сопоставлены.
Если вы выполняете запрос, который не очень избирателен (например, если многие записи соответствуют вашим критериям {category: { $ne:'A'}}
), MongoDB может быть быстрее найти результаты, используя BasicCursor (сканирование таблицы), а не сопоставлять их с индекс.
Порядок полей в запросе обычно не влияет на выбор индекса (есть несколько исключений с запросами диапазона). Порядок полей в сортировке влияет на выбор индекса. Если ваши критерии sort()
не соответствуют порядку индекса, данные результата должны быть повторно отсортированы после использования индекса (вы должны увидеть scanAndOrder:true
в выводе объяснения, если это произойдет).
Также стоит отметить, что MongoDB будет использовать один индекс для каждого запроса (за исключением $or
s).
Итак, если вы пытаетесь оптимизировать запрос:
db.col.find({category:'A'}).sort({updated: -1, rating: -1})
Вам нужно включить все три поля в индекс:
db.col.ensureIndex({category: 1, updated: -1, rating: -1})
FYI, если вы хотите заставить конкретный запрос использовать индекс (как правило, не нужен или рекомендуется), существует опция hint()
, которую вы можете попробовать.
Ответ 2
Это верно, но есть два уровня упорядочения, которые у вас есть, поскольку вы сортируете по составному индексу.
Как вы заметили, когда первое поле индекса совпадает с первым полем сортировки, оно работало, и индекс был замечен. Однако, если работать наоборот, это не так.
Таким образом, своими собственными искажениями заказ, который необходимо сохранить, - это порядок запросов полей от первого до последнего. Анализатор монго может иногда перемещаться по полям в соответствии с индексом, но обычно он просто пытается совместить первое поле, если оно не может пропустить его.
Ответ 3
попробуйте этот код, он будет сортировать данные сначала на основе имени, а затем сохранить "имя" в держателе ключа, он будет сортировать "фильтр"
var cursor = db.collection('vc').find({ "name" : { $in: [ /cpu/, /memo/ ] } }, { _id: 0, }).sort( { "name":1 , "filter": 1 } );