Лучший способ хранить и извлекать синонимы в базе данных MySQL - PullRequest
7 голосов
/ 20 октября 2010

Я делаю список синонимов, который я буду хранить в базе данных и извлекать его перед полнотекстовым поиском.

Когда пользователь вводит как: word1

Мне нужно найти это слово в моей таблице синонимов. Поэтому, если слово найдено, я бы ВЫБИРАЛ все синонимы этого слова и использовал бы его в полнотекстовом поиске в следующем запросе, где я создаю запрос как

МАТЧ (имя столбца) ПРОТИВ ((word1a word1b word1c) В БУЛЕВОМ РЕЖИМЕ)

Так как мне сохранить синонимы в таблице? Я нашел 2 варианта:

  1. с использованием ключевых слов и столбцов слов, таких как

    val  keyword
    -------------
    1    word1a
    1    word1b
    1    word1c
    2    word2a
    2    word2b
    3    word3a
    etc.
    

Итак, я могу найти точное совпадение введенного слова в одном запросе и найти его идентификатор. При следующем выборе я получаю все слова с этим идентификатором и каким-то образом объединяю их, используя цикл записей в языке сервера. Затем я могу построить реальный поиск на главной таблице, в котором мне нужно искать слова.

  1. с использованием только словарных столбцов, таких как

    word1a|word1b|word1c
    word2a|word2b|word2c
    word3a
    

Теперь я выбрал SELECT для своего слова, если оно внутри какой-либо записи, если оно есть, извлеките всю запись и взорвите ее в | и у меня снова есть слова, которые я могу использовать.

Этот второй подход выглядит более легким для поддержки того, кто создал бы эту базу данных синонимов, но я вижу 2 проблемы:

a) Как мне найти в mysql слово, если оно находится внутри строки? Я не могу НРАВИТСЯ «word1a», потому что синонимы могут быть очень похожи в том смысле, что word1a может быть земляникой, а strowberry - птицами, а слово 2a - ягодой. Очевидно, мне нужно точное совпадение, так как же оператор LIKE может точно соответствовать внутри строки?

b) Я вижу проблему со скоростью, я думаю, что если использовать LIKE, потребуется больше mysql take, чем "=", используя первый подход, где я точно сопоставлю слово. С другой стороны, в первом варианте мне нужно 2 оператора: один для получения идентификатора слова и второй для получения всех слов с этим идентификатором.

Как бы вы решили эту проблему, скорее дилемму, какой подход выбрать? Есть ли третий способ, которым я не вижу, что администратору легко добавлять / редактировать синонимы и в то же время быстро и оптимально? Хорошо, я знаю, что обычно нет лучшего способа; -)

ОБНОВЛЕНИЕ : Решение использовать две таблицы, одну для основного слова и второе для синонимов, не будет работать в моем случае. Потому что у меня нет слова МАСТЕР, которое пользователь вводит в поле поиска. Он может ввести любой из синонимов в поле, поэтому мне все еще интересно, как установить эти таблицы, так как у меня нет главных слов, у которых бы были идентификаторы в одной таблице и синонимы с идентификатором мастера во второй таблице. Мастер-слова нет.

Ответы [ 3 ]

10 голосов
/ 20 октября 2010

Не используйте (одну) строку для хранения разных записей.

Другими словами: создайте таблицу слов (word_ID, word) и таблицу синонимов (word_ID, synonym_ID), затем добавьте слово в таблицу слов и одну запись на синоним в таблицу синонимов.

ОБНОВЛЕНИЕ (добавлен 3-й синоним)

Ваша таблица слов должна содержать каждое слово (ВСЕ), ваша таблица синонимов содержит только ссылки на синонимыни единого слова!) ..

Если бы у вас было три слова: A, B и C, которые являются синонимами, ваша БД была бы

WORD_TABLE            SYNONYM_TABLE
ID | WORD             W_ID | S_ID
---+-----             -----+-------
1  | A                  1  |  2
2  | B                  2  |  1
3  | C                  1  |  3
                        3  |  1
                        2  |  3
                        3  |  2  

Не бойтесьмногие записи в SYNONYM_TABLE, они будут управляться компьютером и необходимы для отражения существующих связей между словами.



2-й подход

У вас также может возникнуть соблазн (я не думаю, что вам следует!) Использовать одну таблицу, в которой есть отдельные поля для слова и список синонимов (или идентификаторов) (word_id, word, synonym_list).Помните, что это противоречит принципу работы реляционной БД (одно поле, один факт).

7 голосов
/ 12 июля 2011

Я думаю, что 3 столбца и только одна таблица лучше WORD_TABLE

ID | WORD | GroupID
---+----------------
1  |  A   |   1
2  |  B   |   1
3  |  C   |   1
3 голосов
/ 25 ноября 2013

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

будет хранить слова в таблице слов без синонимов и только с текстом, как это:

Много слов, одно значение

meaning_table

meaning_id
---
1
2
3

И сохраните слова в другой таблице, например, если A, B и C были синонимами 1, означающими

word_table

word_id | meaning_id | word
--------+------------+------
1       |  1         |   A
2       |  1         |   B
3       |  1         |   C

Хотя это очень похоже на то, что предлагает Хасан Амин Саранд , в нем есть ключевое отличие, которое вы не выбираете из WORD_TABLE, а вместо этого выбираете из MEANING_TABLE, это намного лучше, и я узнал, чтотрудный путь.

Таким образом, вы сохраняете значение в одной таблице и столько слов для этого значения, сколько хотите в другой.

Хотя предполагается, что у вас есть 1 значение на слово.

Много слов, много значений

Если вы хотите хранить слова с несколькими значениями, тогда вам нужна другая таблица для отношений «многие ко многим», и все это станет реальностью.es:

meaning_table
-------------
meaning_id
-------------
1
2
3

word_meaning_table
--------------------
word_id | meaning_id
--------+-----------
1       |  1         
2       |  1        
3       |  1         

word_table
--------------
word_id | word
--------+-----
1       |   A
2       |   B
3       |   C

Теперь вы можете иметь столько слов с любым количеством значений, сколько вы хотите, где любое слово может означать все, что вы хотите, и любое значение может иметь много слов.

Если выВы хотите выбрать слово и его синонимы, тогда вы делаете

SELECT 
meaning_id,word_id,word
FROM meaning_table 
INNER JOIN word_meaning_table USING (meaning_id)
INNER JOIN word_table USING (meaning_id)
WHERE meaning_id=1

Вы также можете сохранить значение, у которого еще нет слова или о котором вы не знаете слово.

Если вы не знаете, к какому значению это относится, вы можете просто вставить новое значение для каждого нового слова и исправить значение value_id в word_table позже.

Затем вы даже можете сохранить и выбрать слова, которые являютсяодно и то же, но означают разные вещи

SELECT 
meaning_id,word_id,word
FROM meaning_table 
INNER JOIN word_meaning_table USING (meaning_id)
INNER JOIN word_table USING (meaning_id)
WHERE word_id=1
...