Акцент Нечувствительный порядок в Сфинксе - PullRequest
4 голосов
/ 23 июня 2009

Я использую Sphinx с плагином Thinking Sphinx для поиска моих данных. Я использую MySQL.

Мои данные содержат акцентированные символы ("á", "é", "ã"), и я хочу, чтобы они были эквивалентны их не акцентированным аналогам (например, "a", "e", "a") при поиске и заказе.

Я получил поиск, работающий с использованием таблицы кодировок (pastie.org/204316), и поиск по "AGUA" возвращает "ÁGUA", но упорядочение результатов не работает должным образом. В поиске «AGUA», например, «ÁGUA» следует после «MUITA ÁGUA», но я хотел, чтобы он сортировался так, как если бы он был написан с «A», а не «Á».

Единственное решение, которое я могу придумать, - индексировать новый столбец, содержащий неакцентированные символы, и использовать его для сортировки, используя функцию REPLACE (http://dev.mysql.com/doc/refman/5.4/en/string-functions.html#function_replace) mysql для удаления акцентированных символов, но мне потребуется один вызов ЗАМЕНИТЬ для каждого возможного акцентированного символа (а их много), и мне кажется, это не очень приемлемый обходной путь.

Кто-нибудь знает лучший способ справиться с этой проблемой?

Спасибо!

Ответы [ 3 ]

3 голосов
/ 23 июня 2009

Sphinx обрабатывает сортировку по строковым полям, сохраняя все значения в списке, сортируя список, а затем сохраняя индекс каждой строки как атрибут int. Согласно документации, сортировка этого списка выполняется на уровне байтов и в настоящее время не настраивается.

В идеале строки должны сортироваться по-разному, в зависимости от кодировки и локали. Например, если известно, что строки являются русским текстом в кодировке KOI8R, сортировка байтов 0xE0, 0xE1 и 0xE2 должна привести к 0xE1, 0xE2 и 0xE0, поскольку в KOI8R значение 0xE0 кодирует символ, который (заметно) после символов, закодированных 0xE1 и 0xE2. К сожалению, Sphinx на данный момент не поддерживает это и просто сортирует строки по байтам.

- от http://www.sphinxsearch.com/docs/current.html

Так что нет простого способа достичь этого в Сфинксе. Модификация вашей идеи на основе REPLACE () будет состоять в том, чтобы иметь отдельный столбец и заполнять его с помощью обратного вызова в вашей модели. Это позволило бы вам выполнять замену в Ruby вместо MySQL, что, возможно, более приемлемо для решения.

# save an unaccented copy of your title. Normalise method borrowed from
# /583372/udalenie-aktsentov-diakriticheskih-znakov-stroki-sohranenii-drugih-spetsialnyh-simvolov-proboval-mbchars-normalize
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
1 голос
/ 20 января 2011

Вы также можете использовать специальный индекс, для которого вам даже не нужен новый столбец в вашей базе данных

indexes "LOWER(title)", :as => :title,  :sortable => true

это сырой sql, так что вы можете вызвать метод замены.

0 голосов
/ 04 августа 2016

Просто создайте индекс на строчной версии со следующим синтаксисом. Это очень простое и элегантное решение для поиска case insensitive с использованием Sphinx.

indexes title, as: :title, sortable: :insensitive
...