База синонимов, MySQL. Помогите составить структуру

12
[Удален]
3323

Добрый день, коллеги.

Нуждаюсь в помощи по следующей задаче:

Есть таблица с товарами.

ID, ID поставщика, название, описание, цена и прочее

Туда попадают товары от всех поставщиков.

Но у разных поставщиков один и тот же товар может называться по разному

Apple iPhone 4 - 16GB - Black

iPhone 4 16 black ОРИГІНАЛ

iPhone 4S 16gb

и прочее.

Задача: найти все одним запросом (максимум двумя).

Для этого у нас должна быть еще одна таблица, в которой указано, что все вышеперечисленные названия - синонимы.

Вот как это красиво организовать, я пока не могу придумать. Есть идеи?

S5
На сайте с 04.01.2010
Offline
77
#1

SELECT * FROM tbl_items WHERE id IN (SELECT sinonims FROM tbl_sinonims WHERE id = '$id')

Синонимы перечислять через запятую кажеться

[Удален]
#2

sg552,

что-то я не совсем понял вашу мысль.

Вкратце:

юзер вбивает в строку поиска "Apple iPhone 4 - 16GB - Black"

Мы должны вернуть ему:

Apple iPhone 4 - 16GB - Black

iPhone 4 16 black ОРИГІНАЛ

iPhone 4S 16gb

Причем, даже в ситуации, когда у нас в таблице tbl_sinonims есть запись-синоним "iPhone 4S", а в tbl_items такого товара даже нет, все-равно должен вернуться предыдущий список.

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

KS
На сайте с 11.06.2012
Offline
17
#3

Таблица синонимов уже существует, или вы планируете её как-то создавать?

Я бы не делал отдельную таблицу синонимов, а добавил ещё 1 поле к таблице с товарами:

ID, ID поставщика, название, описание, цена и прочее, ID группы

где "ID группы" - имеет одинаковые значения для товаров-синонимов.

То есть, к примеру:

1,1,Apple iPhone 4 - 16GB - Black,...,1

2,2,iPhone 4 16 black ОРИГІНАЛ,...,1

3,1,Нокия шмокия,...,2

4,2,Нокия хренокия,...,2

Тогда запрос можно будет сделать такой:

SELECT a.название FROM товары a JOIN товары b USING(`ID группы`) WHERE b.название = '$_POST[zapros]'

---------- Добавлено 14.06.2012 в 16:42 ----------

Но если копнуть глубже, и подойти к задаче серьёзнее, то я и это бы не делал. Вам ведь нужно обеспечить чтобы клиент мог находить все интересующие его товары, не зная, как именно они пишутся у разных поставщиков. Я бы сделал Full text index по полю названий товаров, и запускал бы поиск по словам, набранным пользователем. Что-то типа:

SELECT название FROM товары WHERE MATCH (название) AGAINST ('$_POST[zapros]')

Тогда что бы пользователь ни ввёл: "iPhone" или "Apple iPhone" или "iPhone Apple", он получит список всех айфонов.

FileSafe (http://filesafe.anek.ws/) - мониторинг неизменности файлов сайта для защиты от взлома. Для форумчан - первый год бесплатно.
[Удален]
#4

KostaShah, спасибо за ответ, но:

добавил ещё 1 поле к таблице с товарами

я писал

Причем, даже в ситуации, когда у нас в таблице tbl_sinonims есть запись-синоним "iPhone 4S", а в tbl_items такого товара даже нет, все-равно должен вернуться предыдущий список.

лучше отдельную таблицу

Full text index по полю названий товаров

будет не быстр, в БД планируется много миллионов записей.

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

Hkey
На сайте с 30.09.2006
Offline
222
#5

Самый быстрый вариант будет добавить 3-5 полей синоним1, синоним2 ... сделать по ним индекс, хотя памяти будет требовать много. Но для этого нужно изменить архитектуру этой таблицы и объединить одинаковые товары.

В качестве более простого решения есть несколько вариантов их всех щупать нужно:

SELECT * FROM tbl_items WHERE id IN (SELECT sinonims FROM tbl_sinonims WHERE Name = 'НАЗВАНИЕ')

Запрос в скобочках пхп обрабатывает сначала. Но для IN не как и для OR индексы кажись не работают.


SELECT * FROM items
JOIN syn ON items.ID=syn.ID
WHERE syn.Name='НАЗВАНИЕ'

Насчет какой джоин обычный, внутренний, левый или правый - нужно проверять.

---------- Добавлено 14.06.2012 в 18:25 ----------

Если в вариантах с джоином и 2 запросами не работает индекс (см. экспейн), то лучше разбить на N+1 запросов

0. Выбираем ID у синонимов

1..N. В цикле выбираем по ID

P.S. О результатах отпишитесь.

HTraffic.ru (http://HTraffic.ru/) - удобная система для управления контекстной рекламой. тема на форуме (/ru/forum/810827) HTracer (http://htracer.ru/) - скрипт для автопродвижения сайтов по НЧ и СЧ запросам. Для больших сайтов от 100 страниц. (тема на форуме (/ru/forum/676867))
DV
На сайте с 06.03.2012
Offline
71
#6

Это как в том анекдоте:

К пьяному мужику постучали в дверь. Мужик: - Кто там ? Оттуда раздается: - Жан-Клод ван Дамм. На что мужик: - Ща выйду и всем четверым наваляю..

Вообще, зачем изобретать велосипед, если специально для этих целей предусмотрен ( как например в 1С: ) код товара, или иначе, артикул. Т.е. дополнительное поле - ключ

А так можно через

.... LIKE '%iPhone%' AND LIKE '%16GB%' OR .... LIKE '%ОРИГІНАЛ%'

т.е. сперва обязательные условия (AND) , а за ними дополнительные. Но это огород городить..

[Удален]
#7

Я сделал следующим образом

Табличка items

id, name, synonym_group_id

Табличка item_synonyms

id, synonym, synonym_group_id

Запрос

SELECT s.synonym, s.synonym_group_id, i.* FROM (item_synonyms s) LEFT JOIN items i ON s.synonym_group_id = i.synonym_group_id WHERE s.synonym = 'Поисковая строка'

KS
На сайте с 11.06.2012
Offline
17
#8

По моему, правильно. Должно быть довольно эффективно. item_synonyms. synonym конечно имеет индекс?

Чисто из любопытства, вопрос: зачем вам в результатах показывать синонимы, которых нет в таблице айтемов, то есть, как я понял, это будут такие написания товаров, какие ни один поставщик не использует? Я понимаю зачем хранить их в таблице синонимов (чтобы расширить возможности поиска товаров), но зачем выводить их в результате?

[Удален]
#9

Индекс есть.

В результатах показываются не синонимы, а товары, там же left join

Если товаров нет - ничего не отображается

KS
На сайте с 11.06.2012
Offline
17
#10

Тогда один из нас что-то не понимает. На сколько я понимаю этот запрос, он покажет все записи из item_synonyms, соответствующие критерию WHERE (независимо, есть ли соответствующие им записи в items). Для того, чтобы показались только записи, присутствующие в обоих таблицах, нужен простой (INNER) JOIN.

12

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий