- Dataview 把整个 Obsidian 库当作可查询的数据库,数据来自 frontmatter、内联字段(
Key:: Value)与隐式字段(file.*)。 - 四种查询方式:DQL(
dataview代码块)、内联 DQL(`= ...`)、DataviewJS(dataviewjs代码块)、内联 JS(`$= ...`)。 - DQL 查询 = 一个查询类型(必填)+ 可选
FROM(选来源)+ 可选数据命令(WHERE/SORT/GROUP BY/FLATTEN/LIMIT)。 - 常用查询类型:
LIST(列表)、TABLE(表格)、TASK(任务)、CALENDAR(日历)。 - 安全:DQL 是沙箱化的,无法修改库;
dataviewjs拥有与插件同级的权限(可读写文件、发网络请求),只运行可信脚本。
一、什么是 Dataview
Dataview(仓库 github.com/blacksmithgu/obsidian-dataview)把 Obsidian 库当作一个实时索引 + 查询引擎:给笔记打上元数据,再用查询语言把它们列出来、过滤、排序、分组。它只负责展示与计算,不负责编辑笔记。
数据来自三个来源:
---
rating: 8 # 1. YAML frontmatter
reviewed: false
---
基本字段:: 值 # 2. 内联字段(Inline Field)
**加粗字段**:: 也行 # 支持 Markdown 强调包裹键名第 3 类来源是隐式字段(file.*),由 Dataview 自动维护,无需手动书写(见下文)。
二、数据来源(Metadata)
1. Frontmatter
笔记顶部 --- 包裹的 YAML。支持对象、列表等嵌套结构:
---
thoughts:
rating: 8
reviewable: false
tags: [one, two]
---2. 内联字段
正文中直接写 键:: 值:
Basic Field:: Value
**Bold Field**:: Nice!
[mood:: okay]
[length:: 2 hours]规则:内联字段的文本值遇到换行即结束;同一文件内重复的键会自动合并为列表。
3. 隐式字段(file.*,全部可用)
| 字段 | 类型 | 说明 |
|---|---|---|
file.name | Text | 文件名(侧边栏显示名) |
file.folder | Text | 所在文件夹路径 |
file.path | Text | 完整路径(含文件名) |
file.ext | Text | 扩展名,通常 md |
file.link | Link | 指向该文件的链接 |
file.size | Number | 文件大小(字节) |
file.ctime | Date+Time | 创建时间 |
file.cday | Date | 创建日期(仅日期) |
file.mtime | Date+Time | 最后修改时间 |
file.mday | Date | 最后修改日期(仅日期) |
file.tags | List | 全部标签,子标签逐级展开(#Tag/1/A → [#Tag, #Tag/1, #Tag/1/A]) |
file.etags | List | 显式标签,不展开子标签 |
file.inlinks | List | 指向本文件的所有入链 |
file.outlinks | List | 本文件的所有出链 |
file.aliases | List | YAML 中的别名 |
file.tasks | List | 文件内所有任务(- [ ]) |
file.lists | List | 文件内所有列表元素(含任务) |
file.frontmatter | List | 原始 frontmatter 的键值文本 |
file.day | Date | 仅当文件名含日期(yyyy-mm-dd 或 yyyymmdd)或有 Date 字段时存在 |
file.starred | Boolean | 是否在「书签」核心插件中 |
三、数据类型
| 类型 | 说明 | 字面量示例 |
|---|---|---|
| Text | 默认兜底类型 | "hello" |
| Number | 数字 | 6、-80、3.6 |
| Boolean | 布尔 | true / false |
| Date | 日期,匹配 ISO8601(YYYY-MM[-DDTHH:mm:ss.nnn+ZZ]) | date(2021-04-18) |
| Duration | 时长 <时间> <单位>,可用缩写、可复合 | dur(8 minutes)、dur(6hr7min) |
| Link | Obsidian 链接 | [[Page]]、[[Page|显示名]] |
| List | 列表(= 数组),逗号分隔或 YAML 数组 | [1, 2, 3] |
| Object | 对象(仅 YAML 可定义),. 访问子字段 | obj.key1 |
| Null | 空值 | null |
要点:
- 日期可用
.year/.month/.week/.weekday/.day/.hour/.minute/.second等属性;日期 + 时长 = 新日期,日期 - 日期 = 时长。 - 列表:内联文本值要带引号才是列表(
"a", "b");yes, or, no是纯文本。 - 链接写在 YAML frontmatter 里必须加引号(
key: "[[Link]]"),否则 YAML 非法;引号链接 Dataview 认,但 Obsidian 自身不认(无出链、不随重命名更新)。
四、四种查询方式
| 方式 | 语法 | 定位 |
|---|---|---|
| DQL | ```dataview ...``` | 主流方式,管道式、类 SQL,够用 |
| 内联 DQL | `= 表达式` | 在正文任意位置显示单个值 |
| DataviewJS | ```dataviewjs ...``` | 任意 JavaScript,全 API 访问 |
| 内联 JS | `$= js表达式` | 正文内执行任意 JS |
```dataview
table time-played, length, rating
from "games"
sort rating desc
```markdown
我们正在看 `= this.file.name` 这一页。dv.taskList(dv.pages().file.tasks.where(t => !t.completed));本页最后修改于 `$= dv.current().file.mtime`。五、DQL 查询结构
QUERY-TYPE <字段> FROM <来源> <数据命令> <表达式> <数据命令> <表达式> ...只有查询类型是必填,其余可选。
查询类型
| 类型 | 输出 |
|---|---|
TABLE | 表格,每行一条结果,可多列 |
LIST | 要点列表,可在链接旁附带一个字段 |
TASK | 匹配任务的可交互列表 |
CALENDAR | 日历视图,每条命中显示为对应日期的圆点 |
TABLE due, file.tags AS "tags", average(working-hours)CALENDAR file.cday数据命令
| 命令 | 作用 | 关键点 |
|---|---|---|
FROM | 选来源(标签/文件夹/链接) | 至多一个,紧跟查询类型之后 |
WHERE | 按字段值过滤 | 类型不匹配可能出意外结果,建议加 typeof() 检查 |
SORT | 排序 | SORT 字段 ASC/DESC |
GROUP BY | 分组,每组一行 | 组内用 rows 访问被分组的行 |
FLATTEN | 一行拆多行(处理多值/数组字段) | 常用于列表字段展开 |
LIMIT | 限制结果数量 | — |
除 FROM 外,其余命令可多次使用、任意顺序,按书写顺序执行。
LIST WHERE due AND due < date(today)LIST FROM #status/open SORT file.ctime DESC LIMIT 10TASK WHERE !completed SORT created ASC LIMIT 10 GROUP BY file.link SORT rows.file.ctime ASCTABLE L.text AS "My lists" FROM "dailys" FLATTEN file.lists AS L WHERE contains(L.author, "Surname")类型安全示例:字段为
null时比较会产生反直觉结果(null <= date(today)为true),应写成WHERE typeof(due) = "date" AND due <= date(today)。
六、来源(Sources)
用于 FROM,或 JS 中 dv.pages(source)。
| 来源 | 语法 | 示例 |
|---|---|---|
| 标签 | #tagname | LIST FROM #homework |
| 文件夹 | "folder/path"(不带末尾斜杠,匹配含子文件夹) | FROM "projects/brainstorming" |
| 特定文件 | "folder/File"(同名冲突时加 .md) | FROM "30 Hobbies/Games/Dashboard" |
| 指向某笔记的页面 | [[note]] | LIST FROM [[]](当前文件) |
| 某笔记的出链 | outgoing([[note]]) | LIST FROM outgoing([[Dashboard]]) |
组合与取反:and / or(或 AND/OR)组合,- 前缀取反,括号分组:
LIST FROM #food and -#fastfoodLIST FROM #tag and ("folder" or #other-tag)⚠️ 不写
FROM会扫描整个库,大库可能卡住 Obsidian,尽量限定来源。
七、表达式(Expressions)
运算符
| 类别 | 运算符 |
|---|---|
| 算术 | +(加法/字符串拼接)、-、*(乘法/字符串重复)、/、%(取模) |
| 比较 | >、<、=、!=、<=、>= |
| 逻辑 | AND(and)、OR(or)、NOT/!(取反) |
访问
- 列表索引(0 起):
list("A", "B", "C")[0]→"A" - 对象字段:
object.field或object["field"] - 关键字字段名用下标:
row["where"] - 跟随链接:
[[Link]].value取目标页字段(若已有Class:: [[Math]]字段,用Class.timetable而非[[Class]].timetable)
Lambda
CALENDAR file.day
FLATTEN all(map(file.tasks, (x) => x.completed)) AS "allCompleted"
WHERE !allCompleted语法 (arg1, arg2) => 表达式,常用于 map/filter/minby/maxby 等。
八、函数速查
Dataview 内置函数大多支持向量化(对列表逐元素应用)。
构造函数
object(k,v,...) · list(...)(别名 array)· date(text[, format]) · dur(text) · number(text) · string(any) · link(path[, display]) · embed(link) · elink(url[, display]) · typeof(any)
数值
round(n[, digits]) · trunc(n) · floor(n) · ceil(n) · min(...) · max(...) · sum(array) · product(array) · average(array) · reduce(array, 运算)(+/-/*///&/|)· minby(array, fn) · maxby(array, fn)
列表 / 对象 / 数组
contains(容器, 值) · icontains(忽略大小写)· econtains(精确)· containsword · extract(obj, k1, k2...) · sort(list) · reverse(list) · length(x) · nonnull(array) · firstvalue(array) · all(array[, fn]) · any(array[, fn]) · none(array[, fn]) · join(array[, delim]) · filter(array, fn) · unique(array) · map(array, fn) · flat(array[, depth]) · slice(array[, start[, end]])
字符串
regextest(pat, s) · regexmatch(pat, s)(整串匹配)· regexreplace(s, pat, rep) · replace(s, pat, rep) · lower(s) · upper(s) · split(s, delim[, limit]) · startswith(s, pre) · endswith(s, suf) · padleft / padright · substring(s, start[, end]) · truncate(s, len[, suffix])
工具
default(field, value)(null 兜底)· ldefault(非向量化版)· display(any) · choice(bool, left, right)(三元表达式)· hash(seed[, text[, variant]]) · striptime(date) · dateformat(date, fmt) · durationformat(dur, fmt) · currencyformat(n[, code]) · localtime(date) · meta(link)
dateformat()返回字符串(Luxon token 如yyyy-MM-dd),不能直接与date()结果比较;sum([])/average([])空数组返回null。
九、DataviewJS API 速查
dataviewjs 代码块内隐式变量 dv(或 dataview)。⌛ 表示异步(需 await)。
查询
dv.pages() // 全库页面
dv.pages("#books") // 带标签的页面
dv.pages('"folder"') // 某文件夹(注意:文件夹在字符串内也要加引号)
dv.pagePaths("#books") // 只返回路径
dv.page("Index") // 按路径/链接取单页
dv.current() // 当前脚本所在页面渲染
dv.header(1, "标题");
dv.paragraph("段落文本");
dv.span("无内边距的 span");
dv.el("b", "加粗文本", { cls: "my-class", attr: { alt: "x" } });
dv.list(dv.pages().file.link);
dv.taskList(dv.pages("#project").file.tasks.where(t => !t.completed));
dv.taskList(dv.pages("#project").file.tasks, false); // 第二参 false = 不按文件分组
dv.table(["File", "Rating"],
dv.pages("#book").sort(b => b.rating).map(b => [b.file.link, b.rating]));返回 Markdown 的变体:dv.markdownTable() · dv.markdownList() · dv.markdownTaskList()(配合 dv.paragraph() 渲染)。
执行
dv.execute("LIST FROM #tag"); // 内嵌执行 DQL
dv.executeJs("dv.list([1,2,3])"); // 内嵌执行 JS
await dv.view("views/custom", { arg: 1 }); // 加载外部视图脚本(路径从库根算起)工具
dv.array() · dv.isArray() · dv.fileLink() · dv.sectionLink() · dv.blockLink() · dv.date() · dv.duration() · dv.compare(a,b) · dv.equal(a,b) · dv.clone() · dv.parse()
查询求值
await dv.query("LIST FROM #tag"); // 结构化结果
await dv.tryQuery("LIST FROM #tag"); // 失败抛异常
await dv.queryMarkdown("LIST FROM #tag");// 返回 Markdown
dv.evaluate("2 + 2"); // Result 对象(.successful / .value / .error)
dv.tryEvaluate("2 + 2"); // 直接返回值,失败抛异常文件 I/O(dv.io,⌛ 异步)
await dv.io.csv("data.csv"); // 读 CSV → 对象数组
await dv.io.load("File"); // 读文件内容字符串
dv.io.normalize("Test"); // 相对路径 → 绝对路径(同步)十、安全须知
- DQL / 内联表达式是沙箱化的,无法对库做破坏性操作。
dataviewjs/ 内联 JS 拥有与插件同级的权限:可以改写、创建、删除文件,也能发起网络请求。只运行你信任的脚本。