Puisqu'il n'est pas possible de trouver "myrtille" à l'aide du mot "bleu" en utilisant une recherche plein texte mongodb, je souhaite aider mes utilisateurs à compléter le mot "bleu" à "bleuet". Pour ce faire, est-il possible d'interroger tous les mots d'un index de texte intégral mongodb -> que je peux utiliser ces mots comme suggestions, par exemple pour typeahead.js?
Langue d'origine dans la recherche de texte utilise un algorithme pour essayer de relier des mots dérivés d'une base commune (par exemple, "en cours d'exécution" doit correspondre à "en cours d'exécution"). Ceci est différent de la correspondance de préfixe (par exemple "bleu" correspondant "bleuet") que vous souhaitez implémenter pour une fonctionnalité de saisie semi-automatique.
Pour utiliser le plus efficacement typeahead.js
avec la recherche de texte MongoDB, je vous conseillerais de vous concentrer sur le support prefetch
dans typeahead:
Créez une collection keywords
qui contient les mots communs (peut-être avec le nombre de fréquences d'utilisation) utilisés dans votre collection. Vous pouvez créer cette collection en exécuter un mappage/réduire sur l'ensemble de la collection sur laquelle vous avez l'index de recherche de texte, et maintenir la liste de mots à jour à l'aide d'un périodique incrémental mapper/réduire de nouveaux documents sont ajoutés.
Demandez à votre application de générer un document JSON à partir de la collection keywords
avec les mots-clés uniques (peut-être limité aux mots-clés "populaires" basés sur la fréquence des mots pour que la liste reste gérable/pertinente).
Vous pouvez ensuite utiliser les mots-clés JSON générés pour la saisie semi-automatique côté client avec la fonction prefetch
de typeahead:
$('.mysearch .typeahead').typeahead({
name: 'mysearch',
prefetch: '/data/keywords.json'
});
typeahead.js
mettra en cache les données JSON prefetch
dans localStorage pour les recherches côté client. Lorsque le formulaire de recherche est soumis, votre application peut utiliser la recherche de texte MongoDB côté serveur pour renvoyer les résultats complets dans l'ordre de pertinence.
Une solution simple que je suis en train de faire consiste à diviser le texte en caractères individuels stockés dans un tableau indexé par le texte.
Ensuite, lorsque vous exécutez la requête $search
, vous divisez simplement la requête en caractères.
Veuillez noter que cela ne fonctionne que pour les chaînes courtes et que la longueur est inférieure à 32, sinon le processus de construction de l'indexation prendra beaucoup de temps et les performances seront considérablement réduites lors de l'insertion de nouveaux enregistrements.
Vous ne pouvez pas interroger tous les mots de l'index, mais vous pouvez bien sûr interroger les champs du document d'origine. Les mots de l'index de recherche ne sont pas toujours les mots entiers, mais sont quand même tronqués. Donc, vous ne trouverez probablement pas "myrtille" dans l'index, mais simplement "blueberri".
Je ne sais pas si cela pourrait être utile à de nouvelles personnes confrontées à ce problème.
En fonction de la taille de votre collection et de la quantité de RAM dont vous disposez, vous pouvez effectuer une recherche par $ regex en créant l'index approprié. Par exemple:
db.collection.find( {query : {$regex: /querywords/}}).sort({'criteria': -1}).limit(limit)
Vous auriez besoin d'un index comme suit:
db.collection.ensureIndex( { "query": 1, "criteria" : -1 } )
Cela pourrait être très rapide si vous avez assez de mémoire.
J'espère que cela t'aides.
Pour ceux qui n'ont pas encore commencé à mettre en œuvre une architecture de base de données et sont ici pour une solution, optez pour Elasticsearch. C'est une base de données pilotée par un document JSON similaire à mongodb structurellement. Il possède un analyseur "Edge-ngram" qui est vraiment très efficace et rapide pour vous permettre de faire une recherche mal orthographiée. Vous pouvez également rechercher partiellement.