Comment mettre en œuvre la saisie semi-automatique sur un massif de dataset
Je suis en train de mettre en place quelque chose comme Google suggérer sur un site, je suis en bâtiment et je suis curieux de savoir comment le faire sur un très vaste ensemble de données. Bien sûr, si vous avez 1000 points vous mettre en cache les éléments et juste de la boucle à travers eux. Mais comment voulez-vous faire lorsque vous avez un million d'articles? En outre, supposons que les éléments ne sont pas un seul mot. Plus précisément, j'ai été vraiment impressionné par Pandora.com. Par exemple, si vous recherchez "humide", il apporte de retour "Sable Mouillé", mais il apporte aussi de retour de Toad The Wet Pignon. Et leur saisie semi-automatique est RAPIDE. Ma première idée était de regrouper les éléments par les deux premières lettres, de sorte que vous auriez quelque chose comme:
Dictionary<string,List<string>>
où les clés sont les deux premières lettres. C'est OK, mais si je veux faire quelque chose de similaire à Pandora et permettre à l'utilisateur de voir les résultats qui correspondent au milieu de la chaîne? Avec mon idée: Humide ne serait jamais de match de Toad the Wet Pignon car il serait dans le "au seau" au lieu de "NOUS" seau. Alors peut-être que vous pourrait fractionner la chaîne et de "Toad the Wet Pignon" aller dans le "À", "NOUS" et "SP" seaux (bande le mot "LA"), mais quand vous parlez d'un million d'entrées qui peuvent avoir à dire quelques mots de chacun, qui semble comme vous le feriez commencer rapidement à utiliser beaucoup de mémoire. Ok, c'est une longue question. Pensées?
- Pouvez-vous nous donner quelques chiffres à propos de vos données? Combien de chaîne? De longueur moyenne et le nombre moyen de mots? Quelle langue?
- Atteindre 496 000 chaînes actuellement. Durée moyenne de 14 caractères. Nombre moyen de mots 2.3. C#. Oh, et il y a des caractères non-ascii comme Л et И
Vous devez vous connecter pour publier un commentaire.
Comme je l'ai souligné dans Comment mettre en œuvre la recherche incrémentale sur une liste vous devez utiliser des structures comme un Trie ou Patricia trie pour la recherche de motifs dans les textes de grands.
Et pour la découverte de motifs dans le milieu d'un texte il y a une solution simple. Je ne suis pas sûr si c'est la solution la plus efficace, mais j'ai l'habitude de faire comme suit.
Quand j'ai insérer un nouveau texte dans la Trie, je viens de l'insérer, puis retirez-le premier caractère, insérez de nouveau, supprimer le deuxième caractère, insérez à nouveau ... et ainsi de suite jusqu'à ce que l'ensemble du texte est consommé. Ensuite, vous pouvez découvrir tous les sous-chaˆ ıne de chaque texte inséré en une seule recherche à partir de la racine. Cette structure qui en résulte est appelé un Le Suffixe De L'Arbre et il y a beaucoup de possibilités d'optimisation.
Et c'est vraiment incroyable rapide. Trouver tous les textes qui contiennent une séquence de n caractères, vous devez consulter au plus n nœuds et d'effectuer une recherche sur la liste des enfants pour chaque nœud. En fonction de la mise en œuvre (tableau, liste, arbre binaire, sautez la liste des enfants du nœud de collection, vous pourriez être en mesure d'identifier l'enfant nœud, avec aussi peu que 5 étapes de recherche en supposant que la casse des lettres latines seulement. Interpolation tri peut être utile pour des alphabets et des nœuds avec beaucoup d'enfants comme ceux généralement près de la racine.
N'essayez pas de mettre en œuvre vous-même (sauf si vous êtes juste curieux). Utilisez quelque chose comme Lucene ou Endeca - il vous fera économiser du temps et de cheveux.
Pas algorithmiquement liées à ce que vous demandez, mais assurez-vous d'avoir un 200ms ou plus de retard (lag) après la kaypress(es) afin de vous assurer que l'utilisateur a cessé de taper avant l'émission de la requête asynchrone. De cette façon, vous permettra de réduire redondant requêtes http vers le serveur.
Je voudrais utiliser quelque chose le long des lignes d'un trie, et qui ont valeur de chaque nœud feuille une liste des possibilités qui contiennent le mot représenté par le nœud feuille. Vous pouvez trier dans l'ordre de probabilité, ou dynamiquement trier/filtrer en fonction d'autres termes l'utilisateur a entré dans la zone de recherche, etc. Il s'exécute très rapidement et dans une quantité raisonnable de RAM.
Vous conserviez les éléments sur le côté serveur (peut-être dans une DB, si le jeu de données est vraiment vaste et complexe) et que vous envoyer les appels AJAX à partir du navigateur du client permettant de renvoyer les résultats à l'aide de json/xml. Vous pouvez le faire en réponse à l'utilisateur de taper, ou avec une minuterie.
si vous ne voulez pas un trie et que vous voulez des trucs dans le milieu de la chaîne, en général, vous voulez exécuter une sorte de modification de la fonction de distance (distance de levenshtein) qui vous donnera un nombre qui indique le degré de 2 chaînes de match. il n'est pas particulièrement efficace de l'algorithme, mais il n'a pas trop d'importance pour des choses comme les mots, car ils sont relativement courts. si vous êtes en cours d'exécution des comparaisons sur 8000 chaînes de caractères, il va probablement prendre quelques secondes. je sais que la plupart des langages de mise en œuvre, ou vous pouvez trouver un code/pseudo-code assez facilement sur internet.
J'ai construit AutoCompleteAPI pour ce scénario exactement.
Inscrivez-vous pour obtenir un privé de l'index, puis,
Téléchargement de vos documents.
Exemple charger à l'aide de curl sur le document "New York":
Après l'indexation de tous les documents, obtenir des suggestions de saisie semi-automatique, utilisation:
Vous pouvez utiliser n'importe quel client de saisie semi-automatique de la bibliothèque de montrer ces résultats à l'utilisateur.