列表块“一炮三响”问题现状和改进提议

现状

众所周知,一个列表块至少包含了三个块。例如 * foo 的列表块实际的语法树结构和对应的 Markdown 为:

  1. 列表块容器 * foo
  2. 列表项块容器 * foo
  3. 段落块 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 字段完全留空,搜索时仅命中叶子块。

影响范围

广告 我要投放

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • leolee 1 2 赞同
    订阅者

    笔记内容比较多的时候更容易发生的问题是有些内容永远不会被看到 而不是一些内容过多的重复出现 我觉得可能相对偏宽松的命中范围可能比过于范围过于狭小的反馈更有利于笔记的常青

    因为检索需要本身就是因为我们不可能准确记住内容的所在位置而产生,从一个更加宽泛的检索结果去做减法往往比从狭窄的检索结果做加法容易,因为在前面一种情况下我们能看到自己要减去的是一些什么内容,而在后面一种情况下可能连想清楚可能有哪些内容没有覆盖都很难.

  • 其他回帖
  • audiolabj 1 1 赞同
    赞助者 订阅者

    几点浅见:

    1. 对于单一搜索关键词而言,将所有自身 Content 匹配的块(不论是容器块还是叶子块,只要这个块本身的内容(包含扩展属性)匹配搜索条件)作为搜索结果逐条显示,应该符合搜索者的直观期望,所以建议结果中保留这些容器块,可以通过图标和排序的方式(类似于文件命关键字搜索结果中的匹配文件夹和匹配文件的排列)来区隔
    2. 如果除了想获得匹配搜索的节点,还想看到节点归属的各上级容器节点,建议是否可以在结果里包含”块面包屑路径“且路径上每个节点都可以直接点击查看;这样可以解决”查看包含 < 关键字 > 的容器节点“的需求,目前思源给出了结果块归属的文档路径(全路径,但每个节点不可单独点击),是否可以再给出块的面包屑 —— 例如:查询包含 CNN 内容的节点,以及包含这些节点的各层容器块,查询结果中仅列出实际包含该内容的某个块,通过这个块的面包屑路径,自然带出各容器节点,上述容器节点不会直接列在查询结果中,既压缩了结果占用的空间,又可以通过这个结果节点的面包屑直观访问
    3. 对于 fangly 用户提出的复合关键字查询,且每个关键字匹配在不同层级节点的情形,这个在理解上可以类比网页搜索,查看同时包含"foo"和"bar"的内容,一个 content="foobar"的节点属于直观匹配,但是一个二级子节点包含"foo"且四级子节点包含"bar"的容器节点,是否应该符合”直观“的匹配结果呢?如果这个节点符合,那么包含这个节点的所有容器节点,乃至整个文档,以及该文档的父文档,是否也应该算符合呢?毕竟思源笔记的架构上,文档-子文档-容器块-叶子块,在使用逻辑上是无缝的;网页的搜索结果会把包含"foo"和"bar"的网页全部展示,只是按 page ranking 排序,匹配的字加亮显示。因此这样的需求,可能不同的搜索者,期望不同,用”宁可重复,也不漏掉“的原则处理似乎是恰当的。
  • fangly 1
    订阅者

    image.png

    在数据库改进了之后,想要在上面这个图中搜索同时包含 CNN 模型 和 RNN 模型 的块,要写非常非常复杂的 sql 讨论各种情况。

    知道块长什么样的话,那用非常复杂的 sql 肯定能搜出来,但现实使用过程中,我根本无法知道我笔记中“同时包含 CNN 模型 和 RNN 模型”的块是长什么样的,我只知道肯定有容器块包含了它们,而改进后的数据库无法对容器块进行搜索。

    原先的数据库设计下,对于这个场景,虽然可能会有重复,但至少保证我能搜索到所有可能有用的块,最后无非是在 sql 查询结果中看到重复的内容跳过不看,但我用 sql 本来就是在挑选后续可能有用的块,有重复内容其实无所谓,看到重复内容,花 1 秒钟识别出是重复的,跳过就好。

    个人觉得,“搜不到”比“有重复”带来的问题更加严重,一个是功能上的缺失,一个是体验上稍微麻烦点。

    2 操作
    fangly 在 2021-10-15 00:40:46 更新了该回帖
    fangly 在 2021-10-15 00:31:13 更新了该回帖
  • leolee
    订阅者

    例如类似 select * from blocks where content like "%foo%" and depth = "0" 直接匹配 到叶子块
    然后 select * from blocks where content like "%foo%" and depth = "1" 匹配只有一层子块的容器块
    建表的时候文件结构应该已经遍历过了 所以加上深度字段应该不会消耗太多的资源吧
    类似的也可以加上 宽度字段 应该也可以增强检索能力 这个不用管爷爷辈的只管有多少个子块可能会更好弄一点?

  • 查看全部回帖