name: querying-logseq-data version: 1.0.0 description: > 专家在为Logseq DB图数据库构建Datalog查询。当用户需要帮助 编写Logseq查询,理解Datalog语法,优化查询性能, 或使用Datascript查询引擎时自动调用。涵盖高级查询模式,拉取语法, 聚合查询和数据库特定查询技术。 allowed-tools: 读取,搜索,全局搜索,网络获取,网络搜索
查询Logseq数据
何时使用此技能
此技能在以下情况下自动调用:
- 用户想要为Logseq构建Datalog查询
- 关于
:find,:where,:in子句的问题 - 拉取语法问题(拉取?e [*])
- 查询优化或性能问题
- 聚合查询(计数,求和,平均值,最小值,最大值)
- 规则定义或可重用的查询逻辑
- 将简单查询语法转换为完整的Datalog
- 用户在Logseq上下文中提及“Datalog”,“查询”,“datascript”
参考材料:查看{baseDir}/references/query-patterns.md以获取常见查询示例。
您是Logseq数据库图的Datalog查询专家。
Datalog查询基础
基本查询结构
[:find ?variable ; 返回什么
:in $ ?input-var ; 输入($ = 数据库)
:where ; 条件
[?entity :attribute ?value]]
查找规范
;; 返回所有匹配项作为元组
[:find ?title ?author ...]
;; 返回为集合(单个变量)
[:find [?title ...] ...]
;; 返回单个值
[:find ?title . ...]
;; 返回单个元组
[:find [?title ?author] ...]
;; 拉取实体数据
[:find (pull ?e [*]) ...]
[:find (pull ?e [:block/title :block/tags]) ...]
常见查询模式
查找所有页面
[:find (pull ?p [*])
:where
[?p :block/tags ?t]
[?t :db/ident :logseq.class/Page]]
查找具有特定标签/类别的块
[:find (pull ?b [*])
:where
[?b :block/tags ?t]
[?t :block/title "Book"]]
按属性值查找
;; 精确匹配
[:find (pull ?b [*])
:where
[?b :user.property/author "Stephen King"]]
;; 带变量绑定
[:find ?title ?author
:where
[?b :block/title ?title]
[?b :user.property/author ?author]
[?b :block/tags ?t]
[?t :block/title "Book"]]
按状态查找任务
[:find (pull ?t [*])
:where
[?t :block/tags ?tag]
[?tag :db/ident :logseq.class/Task]
[?t :logseq.property/status ?s]
[?s :block/title "In Progress"]]
按日期范围查找
;; 本周到期的任务
[:find (pull ?t [*])
:in $ ?start ?end
:where
[?t :block/tags ?tag]
[?tag :db/ident :logseq.class/Task]
[?t :logseq.property/deadline ?d]
[(>= ?d ?start)]
[(<= ?d ?end)]]
高级查询技术
聚合
;; 按作者统计书籍数量
[:find ?author (count ?b)
:where
[?b :block/tags ?t]
[?t :block/title "Book"]
[?b :user.property/author ?author]]
;; 求和,最小值,最大值,平均值
[:find (sum ?rating) (avg ?rating) (min ?rating) (max ?rating)
:where
[?b :block/tags ?t]
[?t :block/title "Book"]
[?b :user.property/rating ?rating]]
规则(可重用的查询逻辑)
;; 定义规则
[[(has-tag ?b ?tag-name)
[?b :block/tags ?t]
[?t :block/title ?tag-name]]
[(is-task ?b)
[?b :block/tags ?t]
[?t :db/ident :logseq.class/Task]]]
;; 在查询中使用规则
[:find (pull ?b [*])
:in $ %
:where
(has-tag ?b "Important")
(is-task ?b)]
否定
;; 查找没有评分的书籍
[:find (pull ?b [*])
:where
[?b :block/tags ?t]
[?t :block/title "Book"]
(not [?b :user.property/rating _])]
或子句
;; 查找高优先级或逾期的任务
[:find (pull ?t [*])
:in $ ?today
:where
[?t :block/tags ?tag]
[?tag :db/ident :logseq.class/Task]
(or
[?t :logseq.property/priority "High"]
(and
[?t :logseq.property/deadline ?d]
[(< ?d ?today)]))]
递归查询
;; 查找一个块的所有后代
[[(descendant ?parent ?child)
[?child :block/parent ?parent]]
[(descendant ?parent ?child)
[?child :block/parent ?p]
(descendant ?parent ?p)]]
[:find (pull ?c [*])
:in $ % ?root-id
:where
[?root :block/uuid ?root-id]
(descendant ?root ?c)]
拉取语法
选择性属性
;; 特定属性
(pull ?e [:block/title :block/tags])
;; 嵌套拉取引用
(pull ?e [:block/title {:block/tags [:block/title]}])
;; 所有属性
(pull ?e [*])
;; 限制嵌套结果
(pull ?e [:block/title {:block/children [:block/title] :limit 5}])
反向引用
;; 查找引用此实体的所有块
(pull ?e [:block/title {:block/_refs [:block/title]}])
数据库特定查询模式
使用类别
;; 查找所有类别(被标记为标签的标签)
[:find (pull ?c [*])
:where
[?c :block/tags ?t]
[?t :db/ident :logseq.class/Tag]]
;; 查找类别层次结构
[:find ?parent-name ?child-name
:where
[?child :logseq.property.class/extends ?parent]
[?child :block/title ?child-name]
[?parent :block/title ?parent-name]]
使用属性
;; 查找所有用户定义的属性
[:find (pull ?p [*])
:where
[?p :block/tags ?t]
[?t :db/ident :logseq.class/Property]
[?p :db/ident ?ident]
[(clojure.string/starts-with? (str ?ident) ":user.property")]]
;; 查找具有类型的属性值
[:find ?prop-name ?type
:where
[?p :block/tags ?t]
[?t :db/ident :logseq.class/Property]
[?p :block/title ?prop-name]
[?p :logseq.property/type ?type]]
日记查询
;; 查找所有日记页面
[:find (pull ?j [*])
:where
[?j :block/tags ?t]
[?t :db/ident :logseq.class/Journal]]
;; 查找特定日期的日记
[:find (pull ?j [*])
:in $ ?date-str
:where
[?j :block/tags ?t]
[?t :db/ident :logseq.class/Journal]
[?j :block/title ?date-str]]
查询优化提示
- 将最具选择性的子句放在最前面 - 尽早缩小结果范围
- 使用索引属性 -
:db/ident,:block/uuid是索引的 - 避免在拉取中使用通配符 - 指定需要的属性
- 使用规则处理复杂逻辑 - 更好的可读性和潜在的缓存
- 在可能的情况下限制结果 - 为大型数据集添加限制
;; 优化查询示例
[:find (pull ?b [:block/title :user.property/rating])
:in $ ?min-rating
:where
;; 最具选择性的第一个
[?b :user.property/rating ?r]
[(>= ?r ?min-rating)]
;; 然后按标签过滤
[?b :block/tags ?t]
[?t :block/title "Book"]]
Logseq查询UI与原始Datalog
简单查询(UI)
{{query (and [[Book]] (property :rating 5))}}
等效Datalog
[:find (pull ?b [*])
:where
[?b :block/tags ?t]
[?t :block/title "Book"]
[?b :user.property/rating 5]]
高级查询块
#+BEGIN_QUERY
{:title "5-Star Books"
:query [:find (pull ?b [*])
:where
[?b :block/tags ?t]
[?t :block/title "Book"]
[?b :user.property/rating 5]]
:result-transform (fn [result] (sort-by :block/title result))
:view (fn [rows] [:ul (for [r rows] [:li (:block/title r)])])}
#+END_QUERY
常见陷阱
-
MD与DB属性差异
- MD:
:block/content,:block/name - DB:
:block/title,:block/tags
- MD:
-
属性命名空间
- 用户属性:
:user.property/name - 系统属性:
:logseq.property/name
- 用户属性:
-
标签与类别术语
- 在UI中:“标签”
- 在模式中:“类别”(
:logseq.class/*)
-
日期处理
- 日期链接到日记页面
- 使用日期函数进行比较,而不是字符串