现状
众所周知,一个列表块至少包含了三个块。例如 * foo
的列表块实际的语法树结构和对应的 Markdown 为:
- 列表块容器
* foo
- 列表项块容器
* foo
- 段落块
foo
其对应的数据库表行数据为:
类型 | markdown | content |
---|---|---|
l | * foo | foo |
i | * foo | foo |
p | foo | foo |
问题
这就导致在数据库上查询 foo
时,会同时命中三行,也就是“一炮三响”问题。当存在子列表时该问题尤为突出,表现为所有子列表上重复一次。例如:
* foo
* bar
其对应的数据库表行数据为:
类型 | markdown | content |
---|---|---|
l | * foo * bar |
foobar |
i | * foo * bar |
foobar |
p | foo | foo |
l | * bar | bar |
i | * bar | bar |
p | bar | bar |
当搜索 bar
时,会命中 5 行作为结果集。
之前的改进
在搜索时加入了类型过滤,可以设置为过滤容器块,这样上述示例的搜索结果将减少为 1 行,即段落块 bar。
新改进提议
考虑在列表块和列表项块上的 markdown 和 content 字段上仅存储第一个块级子节点内容:
类型 | markdown | content |
---|---|---|
l | * foo |
foo |
i | * foo |
foo |
p | foo | foo |
l | * bar | bar |
i | * bar | bar |
p | bar | bar |
搜索 bar 时命中三行,即仅在当前列表块“一炮三响”。这个改进逻辑也匹配 引用容器块时自动渲染锚文本改进 #3126 和 列表项折叠,除第一个子块外其余子块都隐藏 #3142。
更进一步
容器块上的 markdown 和 content 字段完全留空,搜索时仅命中叶子块。
影响范围
- 对通过子级搜索父级的逻辑会产生影响,比如想搜索同时包含分散在列表项上的某些关键字的父级列表就比较困难,但实现复杂度应该低于之前去重子级的复杂度
- 已有的一些查询逻辑可能会冗余(为了排除父级),但应该不会产生副作用
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于