#sqlite #full-text-search
#sqlite #полнотекстовый поиск
Вопрос:
У меня есть следующие таблицы:
-- table to keep articles titles
CREATE TABLE articles(id, title);
insert into articles (id,title) values (1,'sqlite example');
insert into articles (id,title) values (2,'sqlite query ');
insert into articles (id,title) values (3,'erlang example ');
insert into articles (id,title) values (3,'erlang otp ');
-- table to keep keywords that we would like to search.
create table keywords(id,keyword);
insert into keywords (id,keyword) values (1,'sqlite');
insert into keywords (id,keyword) values (2,'otp');
-- full text search table - copy of articles.
create virtual table articles_fts using fts4 (id,name);
-- populate table with articles titles.
insert into articles_fts(id,name) select id,title from articles;
Теперь я хотел бы найти ВСЕ статьи, содержащие любое из указанных ключевых слов.
Запрос типа:
select * from articles_fts
where name match (select keyword from keywords);
возвращает только заголовки с sqlite в нем (первое ключевое слово), поэтому другие записи таблицы keywords игнорируются.
Вопрос: Как я могу найти все статьи, содержащие любое из указанных ключевых слов? Спасибо.
Ответ №1:
Используйте
select *
from articles_fts
WHERE articles_fts MATCH ( select group_concat(keyword, ' OR ')
from keywords
group by 'x' )
group_concat
Функция объединяет все ключевые слова с запятой. Если вы замените запятые на ИЛИ, это должно привести к хорошему запросу FTS.
Смотрите также раздел 3 ссылки на функцию полнотекстового поиска, касающийся ключевого слова OR и ссылки на агрегатные функции.
Комментарии:
1. Похоже, это не работает: ‘Ошибка: агрегатные функции не разрешены в предложении GROUP BY’, если я делаю это без
GROUP BY 1
‘, ошибки нет, но запрос не возвращает строк : (2. @Anton Prokoiev: Я использую
group by 1
как константу и забыл, что она интерпретируется как ссылка на столбец, попробуйтеgroup by 'x'
вместо этого3. Спасибо, это работает. Единственное замечание: ваш запрос должен выглядеть следующим образом:
Select * from articles_fts where articles_fts MATCH (select group_concat (keyword,' OR ') from keywords group by 'x');
. Поэтому ‘ИЛИ’ должно быть ЗАГЛАВНЫМ , в противном случае оно не отображается как ключевое слово 🙂