MySQL: специальный алгоритм поиска с использованием поиска релевантности MySQL - PullRequest
0 голосов
/ 24 октября 2011

Я пытаюсь выполнить поиск в MySQL, где у пользователя только одно поле.Таблица выглядит следующим образом:

ID          BIGINT
TITLE       TEXT
DESCRIPTION TEXT
FILENAME    TEXT
TAGS        TEXT
ACTIVE      TINYINT

Теперь, если пользователь вводит только blah blubber, поиск должен проверять, появляется ли каждое слово в полях TITLE, DESCRIOTION, FILENAME или TAGS.Сам результат должен быть упорядочен по релевантности, так как часто строка появляется в записи.Я получил данные этого примера:

ID   | TITLE   | DESCRIPTION  | FILENAME | TAGS | ACTIVE
1    | blah    | blah         | bdsai    | bdha | 1
2    | blubber | blah         | blah     | adsb | 1
3    | blah    | dsabsadsab   | dnsa     | dsa  | 1

В этом примере ID 2 должен быть вверху (2 бла, 1 жир), затем 1 (2 бла) и затем 3 (1 бла).Этот процесс должен быть динамическим, чтобы пользователь мог также вводить больше слов, и релевантность работает так же, как с одним или несколькими словами.

Возможно ли это реализовать только в MySQL или мне нужно использовать какой-то PHP?Как это будет работать?

Большое спасибо за вашу помощь!С уважением, Флориан

РЕДАКТИРОВАТЬ: Вот результат после того, как я попробовал ответить Тома Mac:

У меня есть четыре записи, которые выглядят так:

ID  | TITLE | DESCRIPTION | FILENAME | TAGS                          | ACTIVE
1   | s     | s           | s        | s                             | 1
2   | 0     | fdsadf      | sdfs     | a,b,c,d,e,f,s,a,a,s,s,as,sada | 1
3   | 0     | s           | s        | s                             | 1
4   | a     | a           | a        | a                             | 1

Теперь,если я ищу строку s, я должен получить только первые три записи, упорядоченные по значению s.Это означает, что записи должны быть упорядочены следующим образом:

ID | TITLE | DESCRIPTION | FILENAME | TAGS                          | ACTIVE
2  | 0     | fdsadf      | sdfs     | a,b,c,d,e,f,s,a,a,s,s,as,sada | 1        <== 8x s
1  | s     | s           | s        | s                             | 1        <== 4x s
3  | 0     | s           | s        | s                             | 1        <== 3x s

Теперь я попробовал свой запрос следующим образом (имя таблицы PAGES):

select t . *
  from (

        select 
              match(title) against('*s*' in boolean mode) 
            + match(description) against('*s*' in boolean mode) 
            + match(filename) against('*s*' in boolean mode) 
            + match(tags) against('*s*' in boolean mode) 
            as matchrank,
                bb . *
          from pages bb) t
 where t.matchrank > 0
 order by t.matchrank desc

Этот запрос возвращаетэто:

matchRank | ID  | TITLE | DESCRIPTION | FILENAME | TAGS                          | ACTIVE
2         | 2   | 0     | fdsadf      | sdfs     | a,b,c,d,e,f,s,a,a,s,s,as,sada | 1

Это из-за подстановочных знаков?Я думаю, что строка *s* также должна найти значение, равное s ...

Ответы [ 2 ]

2 голосов
/ 24 октября 2011

Это может помочь вам. Тем не менее, предполагается, что в вашей таблице MySQL используется механизм MyISAM:

create table blubberBlah (id int unsigned not null primary key auto_increment,
title varchar(50) not null,
description varchar(50) not null,
filename varchar(50) not null,
tags varchar(50)not null,
active tinyint not null
) engine=MyISAM;

insert into blubberBlah (title,description,filename,tags,active) 
values ('blah','blah','bdsai','bdha',1);
insert into blubberBlah (title,description,filename,tags,active) 
values ('blubber','blah','blah','adsb',1);
insert into blubberBlah (title,description,filename,tags,active) 
values ('blah','dsabsadsab','dnsa','dsa',1);

select t.*
from
(
 select MATCH (title) AGAINST ('blubber blah' IN BOOLEAN MODE)
       +MATCH (description) AGAINST ('blubber blah' IN BOOLEAN MODE)
       +MATCH (fileName) AGAINST ('blubber blah' IN BOOLEAN MODE)
       +MATCH (tags) AGAINST ('blubber blah' IN BOOLEAN MODE) as matchRank,
       bb.*
from blubberBlah bb
) t
order by t.matchRank desc;

EDIT

Другое предположение, которое делает это решение, состоит в том, что искомая строка имеет длину> = 4 символа. Если есть вероятность, что строка «search», то есть «blubber» или «blah», будет иметь длину 1, 2 или 3 символа, тогда вы всегда можете перейти к файлу my.cnf и добавить ft_min_word_len=1 в [mysqld] параметры конфигурации. Затем перезапустите MySQL, и все будет хорошо.

И последнее: если вы планируете использовать этот подход, вам следует добавить FULLTEXT INDEX в каждый из столбцов. Следовательно:

ALTER TABLE blubberBlah add fulltext index `blubberBlahFtIdx1`(`title`);
ALTER TABLE blubberBlah add fulltext index `blubberBlahFtIdx2`(`description`);
ALTER TABLE blubberBlah add fulltext index `blubberBlahFtIdx3`(`filename`);
ALTER TABLE blubberBlah add fulltext index `blubberBlahFtIdx4`(`tags`);

Более подробную информацию о поиске BOOLEAN FULLTEXT вы можете найти в MySQL Docs .

1 голос
/ 06 июня 2012

Вместо поиска «в логическом режиме» используйте Match () Against (), чтобы определить оценку. Добавьте эти оценки, чтобы получить актуальность.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...