web-dev-qa-db-fra.com

Recherche plein texte avec poids en mangouste

Comme je l'ai découvert, depuis la version 3.8.9, les mangoustes prennent en charge la recherche en texte intégral. Mais je ne trouve pas une bonne documentation pour ça!
Je veux faire quelque chose comme:

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
       }
    }
)

Puis-je le faire avec de la mangouste pure? Ou je dois utiliser un plugin comme mongoose-text-search ? Que diriez-vous sans poids?
Et comment dois-je faire?

44
Foad Nosrati Habibi

Oui, vous pouvez utiliser la recherche plein texte dans Mongoose> = 3.8.9. Tout d'abord, une collection peut avoir au plus un index de texte (voir docs ). Donc, pour définir un index de texte pour plusieurs champs , vous avez besoin d'un index composé:

schema.index({ animal: 'text', color: 'text', pattern: 'text', size: 'text' });

Vous pouvez maintenant utiliser $ text opérateur de requête comme ceci:

Model
    .find(
        { $text : { $search : "text to look for" } }, 
        { score : { $meta: "textScore" } }
    )
    .sort({ score : { $meta : 'textScore' } })
    .exec(function(err, results) {
        // callback
    });

Cela triera également les résultats par score de pertinence.

Quant à poids , vous pouvez essayer de passer un objet d'options de poids à la méthode index() (où vous définissez l'index composé) (fonctionnant au moins avec v4.0.1 de mangouste):

schema.index({ animal: 'text', color: 'text', pattern: 'text', size: 'text' }, {name: 'My text index', weights: {animal: 10, color: 4, pattern: 2, size: 1}});
108
eagor

Depuis MongoDB 2.6, une collection peut avoir au plus un index de texte (documenté ici ). Par conséquent, vous ne pourrez pas faire ce que vous voulez avec la version actuelle de MongoDB. Vraiment, pour les problèmes de recherche de texte complexes avec des exigences de poids différents en fonction de l'emplacement de la correspondance, vous devriez envisager une solution de recherche de texte complète comme Solr ou ElasticSearch.

Comme solution de contournement dans MongoDB, vous pouvez symboliser les champs manuellement, les stocker en tant que tableaux de mots clés et les indexer:

animal: ["The", "quick", "brown", "fox", "jump", ..., "dog"]

puis une requête comme

db.test.find ({animal: {$ in: ["brown", "shoes"]})

imite la recherche de texte. Il y a quelques limites à cette approche, comme le travail manuel requis pour la mettre en place, le fait qu'il n'y aura aucune conséquence, par exemple, faire correspondre "rêver" avec "rêver", le fait que les mots vides ne seront pas supprimés comme dans un index de texte normal et absence de tout mécanisme de pondération.

2
wdberkeley

J'ai trouvé l'article suivant qui m'a conduit à http://code.tutsplus.com/tutorials/full-text-search-in-mongodb--cms-24835 J'ai supprimé l'index créé dans le première réponse en utilisant ce qui suit

db.tablename.dropIndex({"indexname_text"})  

J'ai la liste des index avec cette commande

db.tablename.getIndexes()

J'ai ensuite utilisé ce qui suit pour créer les index

db.tablename.createIndex({"$**":"text"})

les commandes suivantes ont fonctionné dans 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);
}
});
1
Gordon Deudney