Поиск текстов по тагам. Построение SQL запроса по КНФ запроса пользователя.
Этот вопрос является продолжением темы http://phpclub.ru/talk/showthread.php?s=&threadid=109792&rand=4.
Необходимость задать этот вопрос была вызвана тем, что к поиску был сделан язык запросов.
Есть 3 таблицы:
таблицы text и tag_to_text связаны как один ко многим.
Есть поисковый запрос приведенный к форме:
(* OR * OR * OR ...) AND (* OR * OR * ...) AND (...) AND ...
где * - это либо слово, либо NOT слово.
К примеру для запроса
(test4_tag1 | test4_tag4 | ~test4_tag3) & ~test4_tag2
будет построен такой SQL запрос:
[sql]
SELECT t.*
FROM text AS t
WHERE
t.group_id IN (4)
AND
EXISTS (
SELECT 1
FROM text_to_tag as t2t
INNER JOIN text_tag as tt on (tt.id = t2t.tag_id)
WHERE
t.id = t2t.text_id
AND (
tt.text = 'test4_tag1'
OR
tt.text = 'test4_tag4'
OR
tt.text != 'test4_tag3'
)
)
AND
NOT EXISTS (
SELECT 1
FROM text_to_tag as t2t
INNER JOIN text_tag as tt on (tt.id = t2t.tag_id)
WHERE
t.id = t2t.text_id
AND
tt.text = 'test4_tag2'
)
ORDER BY t.updated_at DESC
[/sql]
Скажите пожалуйста, на сколько оптимально будет строить запросы подобные этому или есть более оптимальное решение?
А так-же не подскажите ли вы какие индексы лучше расставить по таблицам, чтобы они были наиболее оптимальными?
Этот вопрос является продолжением темы http://phpclub.ru/talk/showthread.php?s=&threadid=109792&rand=4.
Необходимость задать этот вопрос была вызвана тем, что к поиску был сделан язык запросов.
Есть 3 таблицы:
Код:
text:
id - integer
group_id - integer
updated_at - timestamp
tag_to_text:
text_id
tag_id
text_tag:
id
group_id
text - строка
Есть поисковый запрос приведенный к форме:
(* OR * OR * OR ...) AND (* OR * OR * ...) AND (...) AND ...
где * - это либо слово, либо NOT слово.
К примеру для запроса
(test4_tag1 | test4_tag4 | ~test4_tag3) & ~test4_tag2
будет построен такой SQL запрос:
[sql]
SELECT t.*
FROM text AS t
WHERE
t.group_id IN (4)
AND
EXISTS (
SELECT 1
FROM text_to_tag as t2t
INNER JOIN text_tag as tt on (tt.id = t2t.tag_id)
WHERE
t.id = t2t.text_id
AND (
tt.text = 'test4_tag1'
OR
tt.text = 'test4_tag4'
OR
tt.text != 'test4_tag3'
)
)
AND
NOT EXISTS (
SELECT 1
FROM text_to_tag as t2t
INNER JOIN text_tag as tt on (tt.id = t2t.tag_id)
WHERE
t.id = t2t.text_id
AND
tt.text = 'test4_tag2'
)
ORDER BY t.updated_at DESC
[/sql]
Скажите пожалуйста, на сколько оптимально будет строить запросы подобные этому или есть более оптимальное решение?
А так-же не подскажите ли вы какие индексы лучше расставить по таблицам, чтобы они были наиболее оптимальными?