Полнотекстовый поиск с весом в мангусте
Как я узнал, начиная с версии 3.8.9, mongoose поддерживает полнотекстовый поиск. Но я не могу найти хорошую документацию для этого!
Я хочу сделать что-то вроде:
db.collection.ensureIndex(
// Fields to index
{
animal: "text",
color: "text",
pattern: "text",
size: "text"
},
// Options
{
name: "best_match_index",
// Adjust field weights (default is 1)
weights: {
animal: 5, // Most relevant search field
size: 4 // Also relevant
}
}
)
Могу ли я сделать это с помощью чистого мангуста? Или мне нужно использовать какой-то плагин, например mongoose-text-search? Как насчет без веса?
И как мне это сделать?
Ответы
Ответ 1
Да, вы можете использовать полнотекстовый поиск в Mongoose >= 3.8.9. Во-первых, коллекция может иметь не более одного текстового индекса (см. docs). Итак, чтобы определить текстовый индекс для нескольких полей, вам нужен составной индекс:
schema.index({ animal: 'text', color: 'text', pattern: 'text', size: 'text' });
Теперь вы можете использовать $text оператор запроса следующим образом:
Model
.find(
{ $text : { $search : "text to look for" } },
{ score : { $meta: "textScore" } }
)
.sort({ score : { $meta : 'textScore' } })
.exec(function(err, results) {
// callback
});
Это также будет сортировать результаты по оценке релевантности.
Что касается весов, вы можете попробовать передать объект весов опций index()
(где вы определяете составной индекс) (работая хотя бы с v4.0.1 мангуста):
schema.index({ animal: 'text', color: 'text', pattern: 'text', size: 'text' }, {name: 'My text index', weights: {animal: 10, color: 4, pattern: 2, size: 1}});
Ответ 2
Как и в MongoDB 2.6, коллекция может иметь не более одного текстового индекса (документированный здесь). Поэтому вы не сможете делать то, что хотите, с текущей версией MongoDB. Действительно, для сложных задач поиска текста с требованиями разных весов в зависимости от местоположения совпадения вы должны рассмотреть полномасштабное решение для поиска текста, такое как Solr или ElasticSearch.
В качестве обходного пути в MongoDB вы можете локализовать поля вручную, хранить их как массивы ключевых слов и индексировать их:
animal: ["The", "quick", "brown", "fox", "jump", ..., "dog"]
тогда запрос типа
db.test.find({animal: {$ in: [ "brown", "shoes" ]})
имитирует текстовый поиск. Есть несколько ограничений такого подхода, как ручная работа, необходимая для его настройки, тот факт, что не будет происходить, например, совпадение "мечты" со "мечтой", тот факт, что стоп-слова не будут удалены, как в нормальный индекс текста и отсутствие какого-либо механизма взвешивания.
Ответ 3
Я нашел следующую статью, которая привела меня к http://code.tutsplus.com/tutorials/full-text-search-in-mongodb--cms-24835
Я сбросил индекс, созданный в верхнем ответе, используя следующий
db.tablename.dropIndex({"indexname_text"})
Я получил список индексов с помощью этой команды
db.tablename.getIndexes()
Затем я использовал следующее для создания индексов
db.tablename.createIndex({"$**":"text"})
в Mongoose выполнялись следующие команды
model.find(
{$text: {$search: "text you are searching for"}},
{score: {$meta: "textScore"}})
.sort({score:{$meta:"textScore"}}
)
.exec(function(err, results) {
`enter code here`if(!err){
console.log('results ' + results);
}
else
{
console.log(err);
}
});
Ответ 4
var searchQuery=new RegExp('dam', 'i');
var query = { firstName : searchQuery };
Model.find(query ...