分类 标签 存档 订阅 搜索

查询语法

0 浏览0 评论

查询语法

概述

全局搜索 Ctrl​+P​ 支持通过查询语法(Query Syntax)进行高级搜索,以便实现一些逻辑操作,比如包含关键字 foo​ 并且不包含关键字 bar​ 的查询语法为 foo NOT bar​。

在使用查询语法之前,我们先大致了解一下该语法的构成:

  • 字符串(String):由字母、数字等构成
  • 短语(Phrase):由字符串构成
  • 查询(Query):由短语构成,多个查询可通过 ANDORNOT 组合为新的查询

下面我们分别介绍它们的细节。

字符串

字符串可由两种方式指定:

  • 通过英文双引号 " 包裹起来的字符。其中如果需要使用 " 本身,则可通过 SQL 风格转义(再加一个"),例如 "foo""bar""" 将搜索命中 foo"bar"

  • 由非 ANDORNOT 字符组成,并且这些字符必须是:

    • 所有非 ASCII 字符,或者
    • 属于 52 个大小写英文字符(A-Za-z),或者
    • 属于 10 个 ASCII 数字字符(0-9),或者
    • 是下划线 _,或者
    • 是替换符(ASCII 26)

对于非上述的其他字符构成的字符串,必须使用 " 包裹起来,比如包含了 -* 等符号的字符串。

短语

短语由字符串构成,可由 +​ 进行连接。一个短语是由一些记号(Token)有序构成,这些记号由用户的输入文本通过分词器处理得到。思源使用的分词器为了让中文搜索好用(支持单字搜索),所以实现方式是按照字分词的,也就是说每个汉字或者英文字母都会被拆分为一个记号。这对 +​ 连接会产生一些影响,所以如果不确定的话,建议不要使用 +​ 组合多个短语。

查询

查询由多个短语构成,可通过操作符 ANDORNOT 组合为新的查询。

操作符 功能
<query1> AND <query2> query1 和 query2 同时匹配
<query1> OR <query2> query1 或者 query2 匹配
<query1> NOT <query2> query1 匹配同时 query2 不匹配

使用英文圆括号 () 可以组合查询的优先级,例如:

-- 匹配包含 "one" 或者 "two" 的块,不匹配包含 "three" 的块
'one OR two NOT three'

-- 匹配包含 "one" 或者包含 "two" 且不包含 "three" 的块
'one OR (two NOT three)'

使用空格分隔的多个短语默认使用 AND 连接,比如:

'one two three'         -- 'one AND two AND three'
'three "one two"'       -- 'three AND "one two"'
'one OR two three'      -- 'one OR two AND three'

'(one OR two) three'    -- 语法错误!
'func(one two)'         -- 语法错误!

技术实现

我们通过 SQLite FTS5 实现了全局搜索。

系统生成的查询语句关键部分大致是 MATCH '{content name alias memo}:" + query​,query​ 即用户输入部分,对于列过滤器 {content name alias memo}:​ 是通过 设置​ - 搜索​ - 属性​ 生成的。

了解到这些以后,我们就可以通过查询语法来实现查询嵌入块,这样查询性能会更好:

全局搜索 Ctrl​+P​ 支持通过查询语法(Query Syntax)进行高级搜索,以便实现一些逻辑操作,比如包含关键字 foo​ 并且不包含关键字 bar​ 的查询语法为 foo NOT bar​。

除此以外,API 也支持使用 FTS 查询。

大小写敏感

如果开启了 设置 - 搜索 - 区分大小写 选项,则搜索会区分大小写,默认该选项是关闭的,即不区分大小写。

由于分词器是区分大小写的,所以我们构建了两张虚拟表来分别索引:

  • blocks_fts:按字符原样分词
  • blocks_fts_case_insensitive:将英文字母转换为小写分词

这样做的缺点是增加了磁盘空间占用和降低了索引性能,但是目前暂时没有更好的方案,所以只能先这样了。另外,不支持变音符号,仅支持忽略大小写。

如果你有更好的实现方案,欢迎告诉我们,非常感谢。

评论  
留下你的脚步
推荐阅读