Полнотекстовый поиск с весом в мангусте

Как я узнал, начиная с версии 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 ...