判断是否空文档的方法

  1. /api/block/getTreeStat 传入文档 id 即可,返回值有个字段 runeCount​ 代表字符个数的意思 0 是空文档,大于 0 非空文档

    缺点:由于api一次性读入sy文件到内存,文件大的话有性能瓶颈

  2. 通过/api/filetree/getDoc 获取文档的内容,由于这个 api 是动态加载,一般不会加载太多内容,然后空文档的时候,这个返回结果的 content 字段长度是 239,可以依据这长度判断,比如大于 500 铁定非空文档,小于 500 的话,就用 lute 把块转换为 markdown 去掉换行和{: xxx}标记后,看内容是否为空,为空则是空文档,为什么选 500,为了兼容性更好,也可以直接用 239 判断,但不知道不同版本是否有出入。

    缺点:实现复杂

  3. sql查询(批量查询)

    查询是空文档的文档(含目录文档)

    select * from blocks where type='d' and root_id not in (select root_id from blocks where type !='d' and markdown !='' group by root_id)
    
  4. 查询是空文档的文档,排除是目录的文档

    SELECT a.*
    FROM blocks a
    WHERE a.type = 'd'
      AND a.root_id NOT IN (
          SELECT root_id
          FROM blocks
          WHERE type != 'd'
            AND markdown != ''
          GROUP BY root_id
      )
      AND NOT EXISTS (
          SELECT 1
          FROM blocks b
          WHERE b.type = 'd'
            AND b.path LIKE '%/' || a.id || '/%'
            AND b.id != a.id
      );
    

    查询是空文档的文档,排除是目录的文档,优化后的SQL

    SELECT a.*
    FROM blocks a
    WHERE a.type = 'd'
      AND NOT EXISTS (
          -- 排除 root_id 下存在非 d 类型且 markdown 非空的情况
          SELECT 1
          FROM blocks c
          WHERE c.root_id = a.root_id
            AND c.type != 'd'
            AND c.markdown <> ''
      )
      AND NOT EXISTS (
          -- 排除当前 a.id 被其他节点的 path 包含的情况
          SELECT 1
          FROM blocks b
          WHERE b.type = 'd'
            AND b.path LIKE '%/' || a.id || '/%'
            AND b.id != a.id
      );
    

image.png

留下你的脚步
推荐阅读