Logseq Plugins 开发实战
  • Logseq Plugins 开发实战
  • 第一章
    • 搭建开发环境
    • 一个随机句子插件
    • 为logseq添加内容组件
    • 制作一个toolbar仪表盘
    • 制作一个表格生成器
    • 为logseq插件制作设置项
    • 注册Block选项菜单
  • 第二章
    • 适配logseq主题
    • Datascript入门
    • 懒加载与异常处理
  • 第三章
    • 别人的设计:logseq-plugin-tabs为例
    • 发布你的logseq插件到markplace
    • 后记
由 GitBook 提供支持
在本页
  • datascript有什么用?
  • 在Logseq使用
  • 什么是匹配?
  • 多个匹配条件
  • 统计满足条件的block有多少
  • 更多限制条件
  • 在Logseq插件中使用
  • 在插件中使用条件限制
  • Logseq block自带的属性
在GitHub上编辑
  1. 第二章

Datascript入门

上一页适配logseq主题下一页懒加载与异常处理

最后更新于2年前

datascript有什么用?

在Logseq使用

什么是匹配?

datascript是一种匹配查询的语言,我们从最简单的语句开始,一步一步提高直到学会`datascript`。

什么是匹配呢?我们设想Logseq的数据库是长这样的

E-id
Attribute
Value

50

:block/parent

49

50

:block/content

大学数学

51

:block/parent

50

51

:block/content

微积分

52

:block/parent

50

52

:block/content

线代

53

:block/parent

49

53

:block/content

大学英语

这个表在Logseq中看起来是什么样的呢?是这样。微积分和线代的父节点是大学数学。大学数学和大学英语同层级。

我们构造这个命令

[:find ?e 
    :where
     [?e :block/parent 50]]

ps:这是datascript的语法,在logseq中使用还需要加上特定的语法,例:

#+BEGIN_QUERY
{:title "找到父节点为50的节点"
    :query [:find ?e 
    :where
     [?e :block/parent 50]]
}
#+END_QUERY

[?e :block/parent 50]意思就是匹配所有block中parent是50的节点。在我们这里表里面,结果有两个,分别是51和52。那么这个?e就是变量,它的值来源于与:block/parent 50相匹配行的e-id,现在的?e的值是51、52。

(pull 变量名 [*])这个方法的作用是把变量名所对应的block显示出来:

[:find (pull ?e [*])
    :where
     [?e :block/parent 50]]

多个匹配条件

还可能通过多个匹配语句去选择我们想要的block。

现在我们假设我们有一个这样的logseq库。

E-id
Attribute
Value

50

:block/marker

TODO

50

:block/content

学习英语

51

:block/marker

TODO

51

:block/content

学习数学

52

:block/marker

DONE

52

:block/content

学习语文

53

:block/parent

49

53

:block/content

今天天气真好

看起来像这样

我们构造一个筛选出目前还是TODO的任务的条件语句。

 [:find (pull ?e [*]) 
    :where
     [?e :block/marker ?m]
     [(contains? #{"TODO"} ?m)]]

我们来看看这两个条件语句是怎么起作用的。

当匹配条件一[?e :block/marker ?m]执行时,能与:block/marker相匹配的行有三个。 ?e的值有三个50、51、52 。同时?m的值有TODO和DONE两个。

我们用第二个匹配条件[(contains? #{"TODO"} ?m)],要求这个?m是在#{"TODO"}其中。所以?m是DONE的52就被排除了。现在?e只有50和51。

我们用(pull ?e [*])把E-ID为50和51的block显示出来:

统计满足条件的block有多少

如果我们想通知一共有多少个TODO,而不是把他们列出来,我们应该使用 (count 变量名)去替换(pull )。

例:

 [:find (count ?e) 
    :where
     [?e :block/marker ?m]
     [(contains? #{"TODO"} ?m)]]

note 如果想在console中执行datascript可以使用

logseq.api.datascript_query(`
     [:find (pull ?e [*])
    :where
     [?e :block/marker ?m]
     [(contains? #{"TODO"} ?m)]]
`)

更多限制条件

在logseq中我们还可以使用更多的限制条件去筛选block,比如日期等等。

在:input [:today :today]这两个参数传给?start和?end两个变量。然后 [?p :page/journal-day ?d]则把日期赋予?d变量。

最后再把?d与?start和?end进去对比。

#+BEGIN_QUERY
{:title "找出今天的TODO任务数"
    :query  [:find (count ?e) 
    :in  $ ?start ?end
    :where
     [?e :block/marker ?m]
     [(contains? #{"TODO"} ?m)]
     [?p :page/journal-day ?d]
     [(>= ?d ?start)]
     [(<= ?d ?end)]]
    :inputs [:today :today]
}
#+END_QUERY

可以传入:inputs日期的值非常丰富可以自由组合,比如:today、:7d、:56d、:7d-after等等。

在Logseq插件中使用

logseq提供了logseq.DB.datascriptQuery去执行datascript语句。

比如当我们执行

logseq.DB.datascriptQuery(`
     [:find (pull ?e [*]) 
    :where
     [?e :block/marker ?m]
     [(contains? #{"TODO"} ?m)]]
`)

我们尝试执行这个命令并console.log出来看看:

在插件中使用条件限制

在开发中我们只为api提供:query而没有:inputs 。我们应该如何限制查询条件呢?

其实在插件中限制条件还可以更加的灵活与多样。因为可以使用js去往[:find ]中动态的使用的变量。不仅是如[(>= ?d 日期)]还可以在(contains? )中对block内容进行匹配。

只要我们了解相应的格式就行。如日期格式应该满足yyyyMMdd,如果[(>= ?d 20220218)]

Logseq block自带的属性

:Namespace/Attribute
可能的值|示例

:block/uuid

:block/parent

50

:block/left

:block/collapsed?

:block/format

:block/refs

:block/_refs

:block/path-refs

:block/tags

:block/content

:block/marker

"DONE"、"TODO"、 "NOW" 、"LATER"

:block/priority

:block/properties

:block/pre-block?

:block/scheduled

:block/deadline

:block/repeated?

:block/created-at

1644037172307

:block/updated-at

1644037172307

:block/file

:block/heading-level

我的logseq中微积分是72, 线代是73。

我logseq上微积分是72,线代是73