Текстовый поиск MongoDB и несколько поисковых слов
У меня есть указатель на "ключи" массива, которые я использую для обеспечения полнотекстовых функциональных возможностей для моего приложения.
С выпуском 2.4.3 я бы хотел использовать индексный тип текста. Я застраховал "текстовый" тип индекса в "ключах" моего массива и, похоже, работает SUPER быстро (быстрее, чем мой старый текстовый метод).
Проблема заключается в том, что в моем приложении предполагается, что поля включены (AND). По умолчанию текстовые поисковые ORs мои параметры.
Кто-нибудь знает способ запуска текстового поиска включительно?
Например:
db.supplies.runCommand("text", {search:"printer ink"})
должен возвращать результаты как с принтером, так и с чернилами вместо всех результатов с помощью принтера или чернил.
Ответы
Ответ 1
Попробуйте:
db.supplies.runCommand("text", {search:"\"printer\" \"ink\""})
Кроме того, здесь цитата из docs:
Если строка поиска содержит фразы, поиск выполняет И с любые другие термины в строке поиска; например искать "\" мерцание twinkle\ "little star" ищет "мерцание мерцания" и ( "маленькое" или "Звезда" ).
Надеюсь, что это поможет.
Ответ 2
Вы можете обернуть каждое слово в двойные кавычки:
let keywords = ctx.params.query.split(/\s+/).map(kw => `"${kw}"`).join(' ');
match.$text = { $search: keywords, $caseSensitive: false };
Существует недостаток, если пользователь вводит строку с кавычками, это не сработает. Сначала вам придется разбирать строки с кавычками.
Ответ 3
Как ранее указывал @alecxe, чтобы выполнить поиск AND в столбце текстового индекса, вам нужно дважды указать каждое слово поиска. Ниже приведен быстрый однострочный вкладыш для вашего требования.
db.supplies.runCommand("text", {search: "printer ink".split(" ").map(str => "\""+str+"\"").join(' ')})
Ответ 4
Вот простая функция, которую я сделал для поиска с использованием подслов в узле. Надеюсь, это поможет кому-то
Предположим, что пользователь ищет pri nks
поэтому он должен удовлетворять принтеру и чернилам, но текстовый поиск не позволяет этого, так вот моя простая функция:
var makeTextFilter = (text) => {
var wordSplited = text.split(/\s+/);
/** Regex generation for words */
var regToMatch = new RegExp(wordSplited.join("|"), 'gi');
let filter = [];
searchFieldArray.map((item,i) => {
filter.push({});
filter[i][item] = {
$regex: regToMatch,
$options: 'i'
}
})
return filter;
}
и используйте его в своем запросе как это
let query = {...query, $or: makeTextFilter(textInputFromUser)}
tableName.find(query, function (err, cargo_list)