Datascript入门
datascript有什么用?
在Logseq使用
什么是匹配?
datascript是一种匹配查询的语言,我们从最简单的语句开始,一步一步提高直到学会`datascript`。
什么是匹配呢?我们设想Logseq的数据库是长这样的
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。
我的logseq中微积分是72, 线代是73。
(pull 变量名 [*])这个方法的作用是把变量名所对应的block显示出来:
[:find (pull ?e [*])
:where
[?e :block/parent 50]]
多个匹配条件
还可能通过多个匹配语句去选择我们想要的block。
现在我们假设我们有一个这样的logseq库。
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有多少
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提供了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自带的属性
: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
最后更新于