Полнотекстовый поиск SQLite: найдите строки, содержащие любое из ключевых слов

#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'); . Поэтому ‘ИЛИ’ должно быть ЗАГЛАВНЫМ , в противном случае оно не отображается как ключевое слово 🙂