Пример SQLite FTS не работает
Я скачал последнюю оболочку SQLite 3.7.15.2 (Win32) и попытался выполнить один из примеров FTS точно так, как написано на http://sqlite.org/fts3.html
-- Virtual table declaration
CREATE VIRTUAL TABLE docs USING fts3();
-- Virtual table data
INSERT INTO docs(docid, content) VALUES(1, 'a database is a software system');
INSERT INTO docs(docid, content) VALUES(2, 'sqlite is a software system');
INSERT INTO docs(docid, content) VALUES(3, 'sqlite is a database');
-- Return the set of documents that contain the term "sqlite", and the
-- term "database". This query will return the document with docid 3 only.
SELECT * FROM docs WHERE docs MATCH 'sqlite AND database';
но, несмотря на последний комментарий, SELECT привел к пустому набору. Это ошибка в SQLite или просто устаревшая документация? (и какой правильный синтаксис для этого?).
Для меня важнее всего этот запрос
SELECT * FROM docs WHERE docs MATCH '(database OR sqlite) NEAR/5 system';
тоже не работает и такой тип запросов мне нужен в моем приложении. Есть ли другой способ написать так, чтобы он работал?
2 ответа
Пример из документации использует расширенный синтаксис запроса. Проверь это PRAGMA compile_options;
включает в себя ENABLE_FTS3_PARENTHESIS
,
Что твой NEAR
запрос не работает не проблема с параметрами компиляции:
> SELECT * FROM docs WHERE docs MATCH '(database OR sqlite) NEAR/5 system';
Error: malformed MATCH expression: [(database OR sqlite) NEAR/5 system]
Проблема в том, что, согласно документации, NEAR
работает только с основными поисковыми выражениями:
Запрос NEAR задается путем помещения ключевого слова "NEAR" между двумя запросами фразы, термина или префикса.
Таким образом, вы должны переписать поисковое выражение соответственно:
> SELECT * FROM docs WHERE docs MATCH '(database NEAR/5 system) OR (sqlite NEAR/5 system)';
a database is a software system
sqlite is a software system
Я не знаю, является ли это документами или это ошибка в SQLite, но вот несколько альтернатив:
За AND
запросы
Не работает:
select * from docs where docs match 'sqlite AND database';
Работает (используя подразумеваемый AND
):
select * from docs where docs match 'sqlite database';
OR
похоже на работу
select * from docs where docs match 'sqlite OR database';
За OR
+ NEAR
запросы:
Не работает:
SELECT * FROM docs WHERE docs MATCH '(database OR sqlite) NEAR/5 system';
Работает:
SELECT * FROM docs WHERE docs MATCH 'database NEAR/5 system'
UNION
SELECT * FROM docs WHERE docs MATCH 'sqlite NEAR/5 system'
РЕДАКТИРОВАТЬ: Для формы, упомянутой в комментариях (word11 OR word12 OR word13) NEAR/2 (word21 OR word22 OR word23) NEAR/2 (word31 OR word32 OR word33
, Это лучшее, что я мог сделать, это собрать все комбинации вместе с UNION:
SELECT * FROM docs WHERE docs MATCH 'word11 NEAR/2 word21 NEAR/2 word31'
UNION
SELECT * FROM docs WHERE docs MATCH 'word11 NEAR/2 word22 NEAR/2 word32'
UNION
SELECT * FROM docs WHERE docs MATCH 'word11 NEAR/2 word23 NEAR/2 word33'
UNION
SELECT * FROM docs WHERE docs MATCH 'word12 NEAR/2 word21 NEAR/2 word31'
...
Выше, конечно, создает большое количество SQL. Если ваши слова похожи в том, что отличаются только окончания, вы можете использовать подстановочные знаки:
SELECT * FROM docs WHERE docs MATCH 'word1* NEAR/2 word2* NEAR/2 word3*';
Согласно документации ( https://www.sqlite.org/fts3.html) круглые скобки по умолчанию не поддерживаются.
Посмотрите часть 2. Компиляция и включение FTS3 и FTS4.