#mongodb #search #lucene #aggregation-framework #mongodb-atlas-search
#mongodb #Поиск #lucene #агрегация-фреймворк #mongodb-atlas-поиск
Вопрос:
Я знакомлюсь с поиском Lucene и MongoDB Atlas, и у меня есть вопрос об эффективности запроса.
Какой из этих запросов использует меньше ресурсов?
Если есть лучшие запросы для выполнения приведенной ниже задачи, пожалуйста, дайте мне знать.
Я хочу вернуть все фильмы (sample_mflix), которые соответствуют значению заголовка. Фильмы должны быть за определенный год (не должны возвращать фильмы, не относящиеся к этому году), и я хотел бы возвращать фильмы со значениями «$ gte» для фильмов.награды. номинации и фильмы.награды.победы.
Первый запрос кажется более сложным (что, по-видимому, увеличивает использование ресурсов — сложность запроса?). Этот запрос также не возвращает значения только за этот год. Это заставляет меня думать, что, вероятно, есть лучший способ сделать это с помощью Atlas search.
Второй запрос использует $search и $match на разных этапах. Он имеет простой поиск Lucene (который может возвращать больше фильмов, чем первый запрос?), И оператор сопоставления будет фильтровать результаты. Второй запрос более точный — из моих тестов он учитывает ограничение на год. Если я применю этап ограничения, будет ли это лучшим решением?
Если бы эти запросы выполнялись по одному и тому же сценарию, какой из них был бы более эффективным и почему (прошу прощения, второй запрос отформатирован для .net driver)?
new BsonArray
{
new BsonDocument("$search",
new BsonDocument
{
{ "index", "nostoreindex" },
{ "compound",
new BsonDocument
{
{ "must",
new BsonDocument("near",
new BsonDocument
{
{ "path", "year" },
{ "origin", 2000 },
{ "pivot", 1 }
}) },
{ "must",
new BsonDocument("text",
new BsonDocument
{
{ "query", "poor" },
{ "path", "title" }
}) },
{ "should",
new BsonDocument("range",
new BsonDocument
{
{ "path", "awards.nominations" },
{ "gte", 1 }
}) },
{ "should",
new BsonDocument("range",
new BsonDocument
{
{ "path", "awards.wins" },
{ "gte", 1 }
}) }
} }
})
}
против
var searchStage =
new BsonDocument("$search",
new BsonDocument
{
{ "index", "nostoreindex" },
{ "text",
new BsonDocument
{
{ "query", title },
{ "path", "title" }
} }
});
var matchStage = new BsonDocument("$match",
new BsonDocument("$and",
new BsonArray
{
new BsonDocument("year",
new BsonDocument("$eq", year)),
new BsonDocument("awards.nominations",
new BsonDocument("$gte", nominations)),
new BsonDocument("awards.wins",
new BsonDocument("$gte", awards))
})
);
Комментарии:
1. Протестируйте как на своем оборудовании, так и с вашими данными.
Ответ №1:
При использовании Atlas Search лучше избегать использования следующего $match
фильтра после вашего $search
этапа. Это связано с тем, что все данные необходимо будет искать в вашем mongod по идентификатору, что может быть довольно медленным.
Итак, как правило, вы пытаетесь сохранить свой поиск и фильтры «в Lucene», если это возможно, чтобы избежать дополнительного ввода-вывода и сравнений.
В вашем случае вы используете, near
который вернет все результаты в порядке убывания от ближайшего. Вместо этого вы должны использовать range
который может фильтровать эти результаты и ускорить ваш запрос.
near
используется для более высокой оценки ваших результатов, если они ближе к определенному значению, которое может имитировать сортировку. Например, если вы хотите получить результаты с более высокими ‘awards.wins’, вы можете добавить near : { origin: 10000, pivot: 1}
тогда, чем ближе значение к 10000
, тем выше оценка.
new BsonArray
{
new BsonDocument("$search",
new BsonDocument
{
{ "index", "nostoreindex" },
{ "compound",
new BsonDocument
{
{ "must",
new BsonDocument("range",
new BsonDocument
{
{ "path", "year" },
{ "gte", 2000 },
{ "lte", 2000 }
}) },
{ "must",
new BsonDocument("text",
new BsonDocument
{
{ "query", "poor" },
{ "path", "title" }
}) },
{ "should",
new BsonDocument("range",
new BsonDocument
{
{ "path", "awards.nominations" },
{ "gte", 1 }
}) },
{ "should",
new BsonDocument("range",
new BsonDocument
{
{ "path", "awards.wins" },
{ "gte", 1 }
}) }
} }
})
}