Commande insensible au Sphinx
-
06-07-2019 - |
Question
J'utilise Sphinx avec le plugin Thinking Sphinx pour rechercher mes données. J'utilise MySQL.
Mes données contiennent des caractères accentués ("& # 225;", "" # 233; "", "& # 227;") et je veux qu'ils soient équivalents à leurs équivalents non accentués ( "a", "e", "a", par exemple) lors de la recherche et de la commande.
La recherche a fonctionné à l'aide d'une table de jeux de caractères (pastie.org/204316), ainsi qu'une recherche sur "AGUA". renvoie "& # 193; GUA", mais le classement des résultats ne fonctionne pas correctement. Dans une recherche sur "AGUA", "& # 193; GUA" cames après "MUITA", par exemple, mais je voulais que le tri soit effectué comme si elle était écrite avec un "A", pas un "& # 193".
La seule solution à laquelle je puisse penser est d’indexer une nouvelle colonne contenant les caractères non accentués et de l’utiliser pour le tri en utilisant REPLACE ( http://dev.mysql.com/doc/refman/5.4/fr/string-functions.html#function_replace ) Fonction mysql supprimer les caractères accentués, mais il me faudrait un appel à REMPLACER pour chaque caractère accentué possible (et il y en a beaucoup), et il me semble que cette solution de contournement n'est pas très maintenable.
Quelqu'un connaît-il une meilleure façon de gérer ce problème?
Merci!
La solution
Sphinx gère le tri des champs de chaîne en stockant toutes les valeurs dans une liste, en triant la liste, puis en enregistrant l'index de chaque chaîne sous la forme d'un attribut int. Selon la documentation, le tri de cette liste s'effectue au niveau octet et n’est actuellement pas configurable.
Idéalement, les chaînes doivent être triées différemment, en fonction du codage et des paramètres régionaux. Par exemple, si les chaînes sont connues pour être du texte russe dans l'encodage KOI8R, le tri des octets 0xE0, 0xE1 et 0xE2 devrait produire 0xE1, 0xE2 et 0xE0, car dans KOI8R, la valeur 0xE0 code un caractère qui est (sensiblement) après les caractères codés par 0xE1 et 0xE2. Malheureusement, Sphinx ne le supporte pas pour le moment et va simplement trier les chaînes de caractères par octet.
- from http://www.sphinxsearch.com/docs/current.html
Donc, aucun moyen facile d’atteindre cet objectif dans Sphinx. Une modification de votre idée basée sur REPLACE () consisterait à avoir une colonne distincte et à la remplir à l'aide d'un rappel dans votre modèle. Cela vous permettrait de gérer le remplacement dans Ruby au lieu de MySQL, une solution sans doute plus facile à gérer.
# save an unaccented copy of your title. Normalise method borrowed from
# http://stackoverflow.com/questions/522715/removing-accents-diacritics-from-string-while-preserving-other-special-chars-tri
class MyModel < ActiveRecord::Base
before_validation :update_sort_col
private
def update_sort_col
sort_col = self.title.to_s.mb_chars.normalize(:kd).gsub(/[^-x00-\x7F]/n, '').to_s
end
end
Autres conseils
vous pouvez également utiliser un index spécial pour que vous n'ayez même pas besoin d'une nouvelle colonne sur votre base de données
indexes "LOWER(title)", :as => :title, :sortable => true
son sql brut afin que vous puissiez appeler votre méthode de remplacement.
Il suffit de construire un index sur la version minuscule avec la syntaxe suivante. Sa solution très simple et élégante pour la recherche sans distinction de casse
avec Sphinx
.
indexes title, as: :title, sortable: :insensitive