Я пытаюсь создать крошечную поисковую систему с использованием mysql.
Каждое упражнение может иметь произвольное количество поисковых тегов.
Вот моя структура данных:
TABLE exercises
ID
title
TABLE searchtags
ID
title
TABLE exerciseSearchtags
exerciseID -> exercises.ID
searchtagID -> searchtags.ID
... где exercSearchtags - это таблица объединения «многие ко многим», выражающая взаимосвязь между упражнениями и тегами поиска.
Поисковая система принимает неизвестное количество введенных пользователем ключевых слов.
Я хочу ранжировать результаты поиска по количеству совпадений ключевых слов / тегов поиска.
Вот sql, который я сейчас использую для выбора упражнений. Правила CASE и правила WHERE генерируются динамически, по одному для каждого ключевого слова. Например, если пользователь вводит 3 ключевых слова, будет 3 правила CASE и 3 правила WHERE.
SELECT
exercises.ID AS ID,
exercises.title AS title,
(
(CASE WHEN searchtags.title LIKE CONCAT('%',?,'%') THEN 1 ELSE 0 END)+
(CASE WHEN searchtags.title LIKE CONCAT('%',?,'%') THEN 1 ELSE 0 END)+
...etc...
(CASE WHEN searchtags.title LIKE CONCAT('%',?,'%') THEN 1 ELSE 0 END)
) AS relevance
FROM
exercises
LEFT JOIN exerciseSearchtags
ON exerciseSearchtags.exerciseID = exercises.ID
LEFT JOIN searchtags
ON searchtags.ID = exerciseSearchtags.searchtagID
WHERE
searchtags.title LIKE CONCAT('%',?,'%') OR
searchtags.title LIKE CONCAT('%',?,'%') OR
...etc...
searchtags.title LIKE CONCAT('%',?,'%')
GROUP BY
exercises.ID
ORDER BY
relevance DESC
Это почти работает. Однако результаты не ранжируются в порядке, который я ожидаю.
Мое лучшее предположение относительно того, почему это происходит, заключается в том, что оценка релевантности вычисляется ДО того, как строки сгруппированы по упражнению .ID. Поэтому, если при левом соединении конкретное упражнение появляется в наборе результатов 10 раз, а другое - 4 раза, то первое упражнение может получить более высокий балл релевантности, даже если оно не содержит больше соответствий ключевого слова / поискового тега.
У кого-нибудь есть какие-либо предложения / советы о том, как я могу предотвратить это / исправить это?
Спасибо (заранее) за вашу помощь.