我的 Logseq 使用习惯

Logseq 是有一次在跟 Randy 聊天时,他提到最近用得比较多的笔记工具。试用了之后,就被吸引了。经过一段时间摸索,找到了比较舒服的使用姿势,跟大家分享下。

Logseq 是什么

Logseq 是一个以 Outline 为组织形式,以 Block 为核心,支持双向链接和灵活查询的笔记工具。由于它的强大和灵活,很多人(包括我)都用它来 Organize Life。

相比于其他的笔记工具,Logseq 的独特点有:

  • 极低的记录门槛。每天会自动新建 Journal,然后直接写就行了。Outline 模式也让输入变得非常轻量。
  • 强大的查询能力。基于 Outline 组织模式的笔记工具,如果欠缺聚合能力,就容易出现孤岛,Logseq 内置了 Simple Query 和 Advanced Query 两种模式,可以很好地按需聚合内容。
  • 开源。开源给人一种安心感,也能体现创作者对代码的信心。
  • 免费。嗯,这个理由很充分了···
  • Local Data。数据存在本地,不用担心数据泄露或者被用来作为大数据的训练集,也能让 App 的体验更流畅(相比 Online Service,如 Roam Research)。
  • Markdown。没有使用私有格式,其他工具也能打开/浏览文件内容,也方便对数据做二次开发。
  • 活跃的社区。不用担心没人用,导致停止开发,遇到问题也能愉快地交流。

当然槽点也是有的,比如设计上还不够精细,文档也有待完善,Advanced Query 虽然很好用,但门槛也很高。

Logseq 使用起来很自由,但如果缺少规范也容易迷失,无法发挥最大威力,下面就来聊聊我的一些使用经验,仅供参考。

一些概念

Block

Block 是 Logseq 中很重要的一个概念,随便在里面输入一段话,这段话就是一个 Block。Block 可以有 Parent 和 Children

// 每一行都是 Block
// 缩进后会成为 Child Block
// 点击左边的小圆点可以进入到 Block 内页
// 也可以折叠和展开
Logseq 是一个不错的笔记工具
开源且免费
使用方便
...

Page

如果只有 Block,那这些 Block 之间就很难建立关联,Page 可以解决这个问题(Tag 也可以)。只要在一段文字的前后加入两个中括号就行

// Logseq 会自动成为一个 Page,title 就是 Logseq
// 点击进去后还能看到 Back Link,也就是这个 Block
[[Logseq]] 最近的一些更新

Tag

跟 Page 类似,Tag 也可以达到聚合 Block 的效果,只要在前面加上 #。既然两者效果类似,那使用场景有什么区别呢?我的习惯是:如果是一段语句的组成部分就用 Page,其他场景就用 Tag(因为 Tag 无法处理空格,所以我更习惯用 #[[Tag]] 这种形式)。

Logseq 的 advanced query 学起来好累啊 #Thoughts

写一篇 [[关于 Logseq]] 的文章

所有有 Tag 或 Page 的 Block 都会被聚合在一起,同时还会带上日期,这个非常方便。

Properties

Page 和 Block 都可以有自己的属性,对于 Page 来说,第一行如果是 XXX::YYY 这样的形式就会被认为是该页面的属性,对于 Block 则是下一个缩进行。

上图中,关于个人笔记这个页面就有一个 is 的属性,该属性的 value 是 [[Blog]]。结合 Advanced Query 可以实现一些很方便的效果。

Simple Query

Simple Query 比较容易理解,但能力也有限,格式为 {{query (some query detail here)}},常用的有:

{{query #tag}}
{{query [[page]]}}
{{query "full-text search"}}
{{query (and [[project]] (task NOW LATER))}}
{{query (or [[page 1]] [[page 2]])}}
{{query (and (between -7d +7d) (task DONE))}}
{{query (property key value)}}
{{query (page-tags #tag)}}

Advanced Query

Advanced Query 会更复杂,但能力也更强,格式如下:

{:title  [:h2 "Your query title"]
 :query  [:find (pull ?b [*])
          :where ...]
 :inputs [...]
 :view             (fn [query-result] [:div ...])
 :result-transform (fn [query-result] ...)
 :collapsed? true}

这些是 Datalog 的语法,具体解释可见这篇文章

使用要点

标签和属性的选择

通常出于便利考虑,会选择给 Block 加标签,以聚合同类内容,比如 [[pnpm 的设计理念]] 这个包含 Page 的 Block,可以加一个 #[[Frontend]] 标签,这样进入到 Frontend 页面后就能看到 [[pnpm 的设计理念]] 这个 Block 了。

那么这两种用法有什么区别呢?

// Tag
[[pnpm 的设计理念]] #[[Programming]] #[[Frontend]]

// Properties
pnpm 的设计理念
category:: [[Programming]]
sub-category:: [[Frontend]]

直接用 Tag 的话,有两个问题:

  1. 如果 [[pnpm 的设计理念]] 下的内容较多,要分很多天来啃,那么这个 Block 都要手动加上 #[[Frontend]] 这个标签。
  2. 如果要给这个 Block 加上其他的 Tag,如 #[[Build Tool]],那么就要找到所有引用该页面的 Block,挨个加上这个 Tag。

如果最近一段时间在研究这个话题,那么可以每天 copy ref 过来,然后在下面补充学习内容。学习完后,如果其他 Block 要引用 [[pnpm 的设计理念]],比如 正如在 [[pnpm 的设计理念]] 中所说... 这段话,不加标签,那么这个 Block 就会失去跟 [[Frontend]] [[Programming]] 的关联,如果要加标签则容易遗漏,也显得奇怪。

对于会被其他 Block 引用的 Page,可以采用给页面加属性,然后结合 Advanced Query 来实现。

页面属性和高级检索

页面属性上面已有介绍(页面的第一行以 Key::Value 这样的格式书写),我常用的属性有:

  • is: 表示这个 Page 是什么,如 is::[[Blog]]
  • category: 这个 Page 的分类,如 category::[[Programming]]
  • sub-category: 这个 Page 的子分类,如 sub-category::[[Frontend]]
  • medium: 这个 Page 的媒介类型(视频、书、文章等),如 medium::[[Book]]

然后就可以用 Query 把这些 Block 找出来了。比如可以找到所有包含 category::[[Programming]] 属性的页面的 Block。如果只是找出页面是不够的,我们来看下对比。

上面是 Block,下面是 Page,通常我们更想要得到上面的效果。为此,需要写 Advanced Query,下面这段代码会找到所有引用了包含 category 属性为 Programming 的页面的 Block。

#+BEGIN_QUERY
; 以下注释是我查找网上文章结合自己的理解,不一定对
; '?xxx' 表示一个变量
; '$' 表示数据库
; ':xxx' 表示字段和查询关键字
{:title [:h2 "Todo"]
 :query [:find (pull ?b [*]) ;找到所有符合条件的条目,'*' 表示条目的所有字段
 :in $ ?category ;'?category' 就是通过 'inputs' 传过来的变量
 :where
  [?b :block/ref-pages ?p] ;条件语句用 '[]' 表示,?p 是什么下面会说明
  [?p :block/properties ?pr] ;?p 是包含了 properties 为 ?pr 的页面,?pr 是什么,下面会说明
  [(get ?pr :category) ?t] ; get 是获取 object 的属性,并将它设置为 ?t
  [(contains? ?t ?category)]; contains?(注意'?'在后面)表示 predict,也就是符合特定条件
  (not [?b :block/marker ?m]); not [xxx] 表示对 [xxx] 的结果取反
 ]
 :inputs ["Programming"] ; 传入一个参数
}
#+END_QUERY

如果要找到标记为 TODO 的,稍作下调整即可:

#+BEGIN_QUERY
{:title [:h2 "Doing"]
 :query [:find (pull ?b [*])
 :in $ ?category
:where
 [?b :block/marker ?m]
 [(= ?m "TODO")]
 [?b :block/ref-pages ?p]
 [?p :block/properties ?pr]
 [(get ?pr :category) ?t]
 [(contains? ?t ?category)]
]
 :inputs ["Programming"]
}
#+END_QUERY

使用 Copy block embed 来聚合内容到页面

这是某一天的 Journal 页,每天的页面内容大概就是这个样子

可以看到有些 Block 打了标签,有些没有。没打标签的,通常会 Link 到一个 Page,在 Page 里会有相关的属性,通过属性可以将 Block Query 出来。

展开的内容就记在 Block 下,这样回顾时也方便知道每天都记了哪些内容。但这样会比较零散,其他 Block 再引用该 Page 时,只能看到内容分散在不同天的 Block 下。这里有一个 Tip 是使用 Copy block embed。将每天记录的内容 Copy block embeds

然后在对应的页面粘贴即可

在一处编辑,其他地方自动更新。点击右边的数字可以看到原始的内容。这样既可以发挥 Logseq 快速记录的特性,又能让相关内容很好地聚合。

在页面内将相关 Block 按不同维度聚合

因为 Block 与 Page 之间是通过属性间接关联在一起的,所以这些 Block 不会自动出现在该 Page 下,需要通过 Advanced Query 将它们检索出来,相关的 Code 上面已经有了,这里看下展示效果:

划分的维度很简单:

  • Inbox: 没有 Todo 标记的((not [?b :block/marker ?m])),表示将来某一天可以做
  • Todo: 标记为 TODO 的 Block
  • Doing: 标记为 DOING 的 Block
  • Done: 标记为 DONE 的 Block

假如 Todo 列表空了,就从 Inbox 中找几个,状态切换为 TODO ,就会自动出现在 Todo 这个 Group 下。

假如 Doing 的做完了,从 Todo 中找几个,状态切换为 DOING (点击 TODO 按钮即可),就会自动出现在 Doing 这个 Group 下。

一并管理 Todo

用 Logseq 管理 Todo 不是一个顺便的行为,而是合适的行为。对于 Todo 来说,我觉得 Context 是很重要的,而 Logseq 可以为 Todo 提供足够多的 Context,同时可以将 Todo 和其他 Block 联系起来。

场景模拟

今天的待办事项有哪些

先从昨天的 Todo 中找哪些今天可以继续做的,通过 copy ref 的方式,放到今天的 Todo 列表中。

点击进去后可以看到相关的引用

如果这几个 Todo 做完了,可以从其他标为 Favorite 页面的待办里挑几个出来。「挑」的过程就是将 Block 的 /TODO 切换为 /DOING,然后 copy ref 到今天的 Todo 列表里。

做读书笔记

这是 Logseq 的又一个亮点,通过命令 /Upload an asset 上传 PDF 文件后(其实就是将文件拷贝到 Logseq 在本地的目录),点击该文件可以左右分栏,左边是 PDF 电子书,右边是笔记区。阅读过程中,如果有想记录的内容,可以先在 PDF 中高亮,然后右键选择 copy ref,在 Block 中粘贴,就能引用到这些文字了。相比传统的复制粘贴,copy ref 的内容点击后,可以回到 PDF,进而查看更多的上下文。也可以方便地加入自己的 Comment

临时出现的待办事项

可以新建一个 Inbox 页面,然后把事项放到当天的 Journal 页,打上 Inbox 标签。如

• 帮忙调研某个产品 #Inbox
• 用户反馈了个 Bug #Inbox

然后就可以在工作间隙,Review 这些 Inbox 项,看是否应该在今天处理,是否要加上特定的属性(方便归类到特定的页面)。

回顾

回顾是一个很重要的过程,对于学到的内容可以加深印象,了解进行中的事情处于什么状态,帮助制定下一阶段的计划。对于每一个需要回顾的页面,可以都加入到侧栏的 Favorites,同时结合 Advanced Query 把 Block 按 Todo / Doing / Done 区分开来(像 Ideas / Thoughts 这样的页面就不需要了)。

小技巧

  • 输入 / 会出现自动提示,比如设置为 TODO,上传附件等,其中 /Today/Current time 很方便,前者可以自动添加当前日期,如 [[2022-03-24]],这样就会以 Back Link 的形式出现在 2022-03-24 Journal 页。后者会输出当前时间(精确到分钟),可以用来记录时间消耗。/Draw 甚至可以嵌入一个画板。
  • 使用 {{cloze content}} 可以把 content 隐藏起来,点击后展开,可以用来记忆单词。
  • 将常用的结构设置为 Template(比如每天的例行事项,右键点击左边的小圆点可以看到这个选项),在需要的地方选择该模版即可自动填充模版内容。
  • 在设置里开启「Developer mode」后,可以安装 Plugins 和 Themes
  • 按住 Shift 点击 Page 链接,可以在 Sidebar 打开,方便同时浏览
  • 编辑代码或者 Query,可以点击上面的空白区域

小结

以上就是我目前的 Logseq 使用习惯。因为 Logseq 灵活又强大,大家的使用姿势都不太一样,以下这几个链接也可以一并参考:

❤️