MySQL Fulltext Поиск идеографических (азиатских) символов

StackOverflow https://stackoverflow.com/questions/817080

Вопрос

У меня есть база данных, заполненная записями, заполненными азиатскими символами (на китайском, японском и корейском языках), а также база данных, заполненная записями на латинских символах (английская, французская, вы ее называете), и я хочу выполнить полный текст ищет их.

MySQL говорит:

  

Идеографические языки, такие как китайский   и японцы не имеют слова   разделители. Таким образом, FULLTEXT   парсер не может определить где слова   начинаться и заканчиваться в этих и других подобных   языки. Последствия этого   и некоторые обходные пути для проблемы   описаны в разделе 11.8,   & # 8220; Функции полнотекстового поиска & # 8221;.

Раздел 11.8 фактически не предлагает обходных путей и даже не упоминает проблему.

Итак, как бы вы отсортировали поиск по одному китайскому символу в базе данных со смешанными символами ? % LIKE% будет работать, но у него нет отличных оценок релевантности. Должен ли я просто посчитать, сколько раз персонаж появляется в записи, и оценить по этому показателю? Я ценю любые ваши советы. Спасибо!

Это было полезно?

Решение

Это зависит от размера набора данных. Если мы говорим о сотнях тысяч строк, я бы, наверное, взглянул на одно из превосходных доступных независимых решений для полнотекстового поиска. На самом деле мне никогда не приходилось сталкиваться с этой проблемой mysqlf, поэтому я не уверен, какие решения включают поддержку азиатских языков.

Однако я знаю, что в lucene есть анализатор для китайского, японского и корейского языков, поэтому я предполагаю, что что это имеет какую-то поддержку тому, что вы делаете. Обычно, когда мне нужно интегрировать lucene с php, я использую lucene в качестве сервера сокетов и подключаюсь к нему с php.

Если набор данных достаточно мал, возможно, вам будет предложено применить собственный подход. Эта проблема состоит из двух частей: поиск документов для оценки и фактическое ранжирование. Есть несколько способов сделать поиск. Можно использовать LIKE, если набор данных достаточно мал. Другим может быть накатить собственную схему индексации на диске, хотя это будет довольно сложно и отнимает много времени. Вы также можете использовать MySQL в качестве промежуточного пути, как описано ниже.

Чтобы реализовать схему индексирования с использованием MySQL, вам необходимо создать несколько таблиц со следующей структурой:

document
  document_id
  document_text
  document_tokencount

document_token
  document_id
  token_id
  token_docfrequency
  index (token_id, document_id)

token
  token_id
  token_unicode
  token_globalfrequency
  index (token_unicode)

Затем я обрабатываю каждый документ и вставляю строку в таблицу document_token для каждого символа (токена) в документе. Поле token_unicode будет содержать целочисленную последовательность Unicode, используемую для ссылки на этот символ. Поле token_docfrequency содержит целое число, соответствующее количеству раз, которое документ содержит токен, в то время как поле token_globalfrequency содержит общее количество раз, когда термин используется во всех документах.

Это позволит вам быстро выполнять поиск токенов:

SELECT * FROM document_token WHERE token_id = 1
UNION
SELECT * FROM document_token WHERE token_id = 2
UNION
SELECT * FROM document_token WHERE token_id = 3

(объединенный подход - это хак, который позволяет mysql использовать индексы для всех выборок, и, скорее всего, будет быстрее, чем соответствующий запрос, использующий один выбор и несколько операторов или)

Это оставляет нам рейтинг релевантности в качестве остающейся проблемы, о которой вы действительно просили. :) Это можно сделать с довольно хорошими результатами, используя Модель векторного пространства (VSM) .

После выполнения поиска первое, что вам нужно сделать, - это рассчитать tf-idf. оценка за этот токен. Это делается по формуле:

tf-idf = tf(t,d) / tf(d) * log(D / d(t))

where:
tf(t,d) = token frequency in current document
tf(d) = total number of tokens in current document
D = total number of documents
d(t) = number of document that contains the token

Сначала рассчитайте эту оценку для каждого термина в поисковом запросе и сохраните результат в хэш-карте или в чем-то подобном. Это ваш первый вектор, называемый v_1. Затем перейдите к первому документу. Рассчитайте оценку tf-idf для каждого термина в документе и сохраните его как v_2. Теперь вы можете рассчитать оценку для этого документа, используя косинус сходства :

score = arccos(v_1 * v_2 / (|v_1| * |v_2|))

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

Все это может показаться немного сложным, но если у вас есть некоторое базовое понимание линейной алгебры, вы, вероятно, сможете найти рабочее решение за несколько часов. Тем не менее, если это вообще возможно, используйте существующее решение, такое как lucene.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top