New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
数据库表 blocks 加入 depth 字段(一炮三响) #5769
Comments
@lengyu-lys 这个改进的主要思路是 l 保存完整 md,i 的话仅保存第一个子块 md,是这样对吗? |
能否做到分别进行以下查询(没有一炮三响): 1、查询出文档 A 中所有的任务项(每个任务项的层级各不相同) |
roam的query能实现以下查询,这也是roam中最基础最常用的query之一,也就是查询同时包含关键词foo1和关键词foo2的块,而且这两个关键词可能不在一个block里面,有三种情况:1、foo1和foo2在一个block里面,2、包含foo1的block的一个子块含有foo2,3、包含foo2的block的一个子块含有foo1。下面这个图片就是第2种情况: 如果l 保存完整 md,i 的话仅保存第一个子块 md,加入depth,我没想到如何较为简便地实现上面这个查询 这篇文章介绍了一些roam的数据结构:https://sspai.com/post/65426 ,虽然roam和思源数据库完全不是一个类型,不过或许会有一些启发 |
看来还得继续考虑,先关闭了,感谢各位帮忙。 |
这个通过深度是可以的呀, 不要通过 i 类型查询,而是通过 l 类型查询。我理解下面的 sql 应该就可A以满足你的需求 SELECT * FROM block WHERE markdown like '%[[foo1]]%[[foo2]]%' AND type = 'l' ORDER BY depth DESC limit 1 |
按照您之前的说法,siyuan是可以实现类似的搜索,只不过比较复杂,这个是 sql 搜索语法和 roam 搜索语法的区别造成的,感觉和这次讨论的问题关系不大。引入 depth 并不会和您搜索的问题产生冲突,同时会解决很多其它的问题,因此我认为引入depth是有意义的。 关于您提出的问题,我觉得应该单独开一个 issue 提出对 搜索语法进行优化(比如可以效仿roam 语法之类的) |
roam/logseq 中的数据库roam的数据库中,每个块的 有了这个父级id列表后,在{{[[query]]: {and: [[foo1]] [[foo2]]}}}时,对于某个块,除了看自己的内容中有没有满足要求,还会同时看所有的父级id所对应的内容,可以等价于说某个block的content是自己的content加上所有父级块的content,但这个content是在query的过程中实时计算的,而思源可以理解成是预先存储这些content的(当然还是有不小区别的,roam中看某个块的所有父级,思源是存储某个块的所有子级,不过本质上差不多),某种程度上思源现有的技术方案是用空间换时间。只存储一个父块的id在理论上也可以搜,但在时间效率和实现复杂度上会差很多。(这段内容是我根据roam的数据库结构猜测的roam的query的实现方案,目前没找到相关资料,有可能roam在实现时和我说的有差异) 此外,roam的 logseq中,每个块的 logseq 中 query 的具体实现我目前没有找到roam的query的实现方案,logseq的query原理有一些资料我研究了下,这里简单介绍下。 例如{{[[query]]: {and: [[foo1]] [[foo2]]}}}在logseq中会先转化为: {:query
[:find
(pull
?b
[:db/id
:block/uuid
:block/parent
:block/left
:block/collapsed?
:block/format
:block/refs
:block/_refs
:block/path-refs
:block/tags
:block/content
:block/marker
:block/priority
:block/properties
:block/pre-block?
:block/scheduled
:block/deadline
:block/repeated?
:block/created-at
:block/updated-at
:block/file
:block/heading-level
{:block/page
[:db/id :block/name :block/original-name :block/journal-day]}
{:block/_parent ...}])
:in
$
%
:where
(page-ref ?b "foo1")
(page-ref ?b "foo2")],
:query-string "(and [[foo1]] [[foo2]])",
:rules
[[(page-ref ?b ?page-name)
[?b :block/path-refs [:block/name ?page-name]]]]} 这一段代码的核心内容就是最后面对 思源中的一种解决方案一种解决方案是,类似roam,在数据库中加入每个块的父级id列表(不需要加入depth,这个列表本身其实也包含了depth信息),然后列表项块和列表块等容器块的content可以直接留空(存储第一个块级子节点内容这个我觉得没有必要了,直接一步到位吧)。 类似roam的 但是只改一个数据库肯定是远远不够的,只改动数据库那就是自废武功了,原先很容易实现的查询现在变得麻烦很多,配套的需要增强sql功能,类似roam/logseq封装出query一样封装出一个新的sql语法,再进一步可以封装出可视化sql。 (我还没想出来在这种数据库设计下怎么用sql实现类似{{[[query]]: {and: [[foo1]] [[foo2]]}}}这种多关键字查询且关键字在不同层级上的情况,理论上可以,不过我sql功力有限,目前还不知道怎么实现以及实现复杂度如何) 但是改动sql的工作量肯定很大,所以说当下思源的技术方案可以说就是用空间换时间,这个时间包括查询时间(现有的思源数据库某种程度上相当于预先存储查询所需的content)和开发时间。 初心回到D大当时提这个改进的初心,我想其中一个应该是从用户角度考虑为了提高新手的用户体验,但是,“列表块和列表项块上的 markdown 和 content 字段上仅存储第一个块级子节点内容”这个技术方案并没有提高新手的用户体验,因为用户想要真正解决“一炮三响”,还必须理解列表块、列表项块、段落块然后在sql中筛选,而估计有九成用户并不完全清楚这些块的准确含义,而且他们也没有动机去理解这些内容,理想情况思源也应当能让尚未准确理解思源块类型的用户轻松使用sql,而如果用户理解了思源的块类型,这是一个用户门槛,那么他理解去重的逻辑也很容易。 所以,想要提高用户体验,正确的路子应该是可视化sql或者像roam那样封装出query,改数据库并不能直接提高新手的用户体验。 D大提到“比如想搜索同时包含分散在列表项上的某些关键字的父级列表就比较困难,但实现复杂度应该低于之前去重子级的复杂度”,我认为恰好反过来,去重的复杂度低于搜索多关键字的复杂度,这复杂度不仅是针对用户的还是针对开发者的,而且我还可以选择不去重,但改进数据库后用户必须面对多重关键字搜索难度上升的问题,所以需要配合sql的改进才算完整的改进方案。 我觉得D大提这个改进还可能是从技术角度考虑觉得原先的技术方案不太优雅,因为数据库中有很多冗余数据。我认为这是一个用空间换时间的技术方案,没什么不好的。改动之后的技术方案肯定会更加优雅,有时间肯定还是要改进的,但要配合sql改进才完整,工作量应该不小,我觉得应该等到D大准备搞可视化sql之类的sql改进功能时再考虑这个问题。(顺带附上roam的可视化query插件链接,可能有参考价值:https://github.com/dvargas92495/roamjs-query-builder ) |
很棒的分析,我觉得其实以 siyuan 的存储方式也可以实现类似的搜索,只不过是要通过 parent_id 逐步递归,效率会低很多。我也赞同你的观点:sql 语句不适合作为面向用户的搜索语言, 因为 sql 对于普通用户来说比较复杂非常难写。类似于 roam 那样的搜索语法确实更加简洁高效,不过要支持类似的语法的话成本就很高了,这个估计 D大 会需要更慎重的考虑。其实我觉得与其改变数据库,不如专门做一个搜索用的索引库,这样将元数据存储和搜索的索引分开维护,这样对现有系统影响更小,同时可以采用更加灵活的搜索方案或组件(比如 elastic search等)。 |
看了下相关讨论,个人觉得添加一个 depth 能解决很大一部分的问题,这个 depth 值得是当前块在整个列表中的深度。
比如:
对应的数据库:
这样根据 type、subtype、depth就能够解决很多关于列表项区别的问题了
Originally posted by @lengyu-lys in #5717 (comment)
The text was updated successfully, but these errors were encountered: