Збіг MySQL () проти () - порядок за релевантністю та стовпчиком?


80

Гаразд, отже, я намагаюся здійснити повнотекстовий пошук у кількох стовпцях, щось таке просте:

SELECT * FROM pages WHERE MATCH(head, body) AGAINST('some words' IN BOOLEAN MODE)

Тепер я хочу впорядкувати за релевантністю (скільки слів знайдено?), Що мені вдалося зробити приблизно таким чином:

SELECT * , MATCH (head, body) AGAINST ('some words' IN BOOLEAN MODE) AS relevance 
FROM pages
WHERE MATCH (head, body) AGAINST ('some words' IN BOOLEAN MODE)
ORDER BY relevance

Тепер наступає та частина, коли я загублюсь, я хочу надати пріоритет релевантності в headколонці.

Я думаю, я міг би зробити два стовпці релевантності, один для headі один для body, але на той момент я б виконував приблизно однаковий пошук у таблиці три рази, і для того, що я роблю цю функцію, важлива продуктивність, оскільки Запит буде об'єднано та зіставлено з іншими таблицями.

Отже, моє головне питання полягає в тому , чи існує більш швидкий спосіб пошуку релевантності та визначення пріоритетів певних стовпців? (А як бонус, можливо, навіть підрахування релевантності, скільки разів слова трапляються у стовпцях?)

Будь-які пропозиції чи поради були б чудовими.

Примітка: Я буду запускати це на LAMP-сервері. (WAMP при локальному тестуванні)


Чи справді ви повинні вставити MATCH ... ПРОТИ як в речення SELECT, так і в речення WHERE? Чи не можете ви вказати псевдонім у реченні SELECT та посилатися на псевдонім у реченні WHERE? Я намагаюся використовувати підготовлені висловлювання, і це здається мені зайвим / дивним.
S. Imp

2
Ні, як зазначено в документації MySQL, починаючи з 5.5, MATCH ... ПРОТИ обчислюється один раз, як в SELECT, так і WHERE, тому ніяких додаткових накладних витрат.
Bob2u

Відповіді:


156

Це може надати підвищеної відповідності тій частині голови, яку ви хочете. Це не подвоїть, але, можливо, досить добре заради вас:

SELECT pages.*,
       MATCH (head, body) AGAINST ('some words') AS relevance,
       MATCH (head) AGAINST ('some words') AS title_relevance
FROM pages
WHERE MATCH (head, body) AGAINST ('some words')
ORDER BY title_relevance DESC, relevance DESC

-- alternatively:
ORDER BY title_relevance + relevance DESC

Альтернативою, яку ви також хочете дослідити, якщо у вас є можливість змінювати механізм БД, є Postgres . Це дозволяє встановити вагу операторів і пограти з рейтингом.


14
Окрім того, MySQL 5.6 підтримує повнотекстовий пошук за таблицями InnoDB!
Джабарі

1
Чи можете ви надати для цього скрипт SQL?
Користувач

Наскільки негативний вплив мають кілька пошукових запитів? Мені знадобиться 4 збіги ion my SELECT, оскільки у мене є 4 різні коефіцієнти ваги. Чи не зменшить це продуктивність?
ToBe

@ToBe Я бачив на інших подібних запитаннях більше, ніж одна людина каже, що не існує зайвих накладних витрат при використанні декількох MATCHвисловлювань через внутрішню роботу MySQL.
BadHorsie

Обов’язково запустіть ці два. ALTER TABLE talk_webpages ADD FULLTEXT(head)таALTER TABLE talk_webpages ADD FULLTEXT(head, body)
Супун Кавінда

15

Просто додаю для тих, хто може знадобитися .. Не забудьте змінити таблицю!

ALTER TABLE table_name ADD FULLTEXT(column_name);

3
якщо ви виконаєте вищезазначену команду більше одного разу, це створить кілька індексів для одних і тих же стовпців. Тож просто запустіть цю команду лише один раз.
hakiko

А ще краще, використовуйте CREATE FULLTEXT INDEX ім’я індексу в назві таблиці (імена стовпців). Вам також слід реально перевірити, чи існує індекс, перш ніж намагатися його створити. Ви можете перевірити, чи існує він, використовуючи: SELECT INDEX_NAME FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_CATALOG= 'def' AND TABLE_SCHEMA= DATABASE () AND TABLE_NAME= 'tablename' AND INDEX_NAME= 'indexname';
Дейв Хілдітч,

9

Я ніколи цього не робив, але, здається, так

MATCH (head, head, body) AGAINST ('some words' IN BOOLEAN MODE)

Має надати подвійну вагу сірникам, знайденим в голові.


Просто прочитайте цей коментар на сторінці документів , Думаючи, що він може бути для вас цінним:

Опублікував Патрік О'Лайн, 9 грудня 2002 р., 06:51

Слід зазначити в документації, що IN BOOLEAN MODE майже завжди повертатиме значення 1,0. Для того, щоб отримати значущу релевантність, вам потрібно:

SELECT MATCH('Content') AGAINST ('keyword1 keyword2') as Relevance 
FROM table 
WHERE MATCH ('Content') AGAINST('+keyword1+keyword2' IN BOOLEAN MODE) 
HAVING Relevance > 0.2 
ORDER BY Relevance DESC 

Зверніть увагу, що ви робите регулярний запит релевантності, щоб отримати фактори релевантності у поєднанні з реченням WHERE, що використовує BOOLEAN MODE. BOOLEAN MODE надає вам підмножину, яка відповідає вимогам пошуку BOOLEAN, запит релевантності відповідає коефіцієнту релевантності, а речення HAVING (у даному випадку) гарантує відповідність документа пошуку (тобто документи, оцінка яких менше 0,2 вважаються недоречними). Це також дозволяє замовляти за релевантністю.

Це може бути або не бути помилкою в тому, як функціонує IN BOOLEAN MODE, хоча коментарі, які я читав у списку розсилки, свідчать про те, що рейтинг відповідності IN BOOLEAN MODE не дуже складний, отже, він погано надається для фактичного надання відповідних документів. До речі - я не помітив втрати продуктивності для цього, оскільки, здається, MySQL виконує пошук FULLTEXT лише один раз, хоча два речення MATCH різні. Використовуйте ПОЯСНЕННЯ, щоб довести це.

Тому, здається, вам не доведеться турбуватися про те, щоб двічі викликати повнотекстовий пошук, хоча вам все одно слід "використовувати EXPLAIN, щоб довести це"


1
Двічі додавання голови до функції match () не працює, на жаль. Може тому, що запит не враховує, скільки разів слова зустрічаються? І я також використовую цю сторінку, на яку ви посилаєтесь, але я з якихось причин не можу зробити так, щоб вона працювала ... Я ще не проіндексував свої стовпці, і тому не можу здійснювати пошук без тегу "В РЕЖИМІ БУЛІВСЬКОГО". .
Крістоффер ла Кур

Я думаю, що небулевий пошук поверне # випадків, але булевий ні?
jisaacstone

Завтра я детальніше розгляну це, але поки що збираюся затриматися. Дякую за відповідь, ми побачимо, чи допоможе мені це, коли я це зрозумію.
Kristoffer la Cour

У мене виникла проблема з використанням В РЕЖИМІ BOOLEAN, а потім впорядкування за релевантністю, і це вирішило мою проблему з релевантністю, яку завжди повертали як 1. Дякую.
Jazzy

Створення поля оцінок вирішило мою проблему: я отримував результати, але багато з них були повним шумом. Дякую, +1
Кріс Бейкер

4

Я теж просто бавився з цим. Один із способів додати зайву вагу - це область ЗАМОВИТИ ЗА КОДОМ.

Наприклад, якщо ви відповідали 3 різним стовпцям і хотіли б важче зважити певні стовпці:

SELECT search.*,
MATCH (name) AGAINST ('black' IN BOOLEAN MODE) AS name_match,
MATCH (keywords) AGAINST ('black' IN BOOLEAN MODE) AS keyword_match,
MATCH (description) AGAINST ('black' IN BOOLEAN MODE) AS description_match
FROM search
WHERE MATCH (name, keywords, description) AGAINST ('black' IN BOOLEAN MODE)
ORDER BY (name_match * 3  + keyword_match * 2  + description_match) DESC LIMIT 0,100;

Це не справді важкий запит?
Beanow

5
Перемістіть математику в оператор select, і це значно полегшить навантаження. SELECT search.*, (MATCH (name) AGAINST ('black' IN BOOLEAN MODE) * 3) + (MATCH (keywords) AGAINST ('black' IN BOOLEAN MODE)*2 + MATCH (description) AGAINST ('black' IN BOOLEAN MODE)) AS totalScore , FROM search WHERE MATCH (name, keywords, description) AGAINST ('black' IN BOOLEAN MODE) ORDER BY totalScore DESC LIMIT 0,100;
invertedSpear
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.