快速上手:把 Obsidian 笔记库变成可查询数据库的 3 步(Dataview 指南)
【免费下载链接】obsidian-dataviewA data index and query language over Markdown files, for https://obsidian.md/.项目地址: https://gitcode.com/gh_mirrors/ob/obsidian-dataview
在 Obsidian 里管理几百篇笔记时,想找"去年读过的、评分 9 以上的科幻小说"只能逐篇点开翻。Dataview 是一个 Obsidian 插件,作用是把你的笔记库变成可查询的数据库:它先索引你在 Markdown 里标注的元数据,以及文件名、标签、任务等自动生成的字段,再用一条查询语句完成筛选、排序、分组和展示。整个流程就三步:标数据、写查询、调组合。
📎 标注笔记:把元数据变成可查询的字段
Dataview 只能查询它"看得见"的数据。让数据被看见有三种方式:
| 方式 | 语法 | 适合放什么 |
|---|---|---|
| YAML 前置元数据 | 笔记顶部的---块 | 整篇笔记的属性,如评分、作者、类型 |
| 行内字段 | rating:: 9或[rating:: 9] | 紧贴某一行文字或某个任务的数据 |
| 内置字段 | 无需标注 | 文件名、标签、任务、创建时间,自动索引 |
--- genre: "科幻" rating: 9 time-read: 2021-03-03 ---这三行写在笔记开头,genre、rating、time-read就能被查询到。日期写成YYYY-MM-DD格式会被识别为日期类型,之后可以直接做大小比较。
行内字段则写在正文里,不用翻回笔记顶部:
《沙丘》这个月读完了。[rating:: 10] [mood:: 略长但值得] - [ ] 重写这篇书评 [due:: 2021-04-10]前一行把评分和感受嵌在句子里;第二行给一个任务加了截止日期due,任务和列表项的字段必须用方括号语法包住,才能挂到这一行上。
🔍 写出第一条查询:把文件夹渲染成排序表格
新建一篇笔记,粘入这个最小可运行示例,切到预览模式即可看到结果:
TABLE time-played AS "游玩时间", length AS "时长", rating AS "评分" FROM "games" SORT rating DESC这几行做了三件事:TABLE指定按表格输出三列;FROM "games"把数据范围限定在 games 文件夹及其子文件夹里的笔记;SORT rating DESC按评分从高到低排序,AS "评分"只是改列标题,不改数据。渲染效果如下:
Dataview TABLE 查询结果:13 条游戏笔记按评分降序排列,名称列可点击跳转到对应笔记
📊 组合数据命令:筛选、排序、分组复用
除FROM外(最多一条,且必须紧跟查询类型之后),其余命令可以写多条、任意顺序,Dataview 按书写顺序逐条执行。
筛选并排序
WHERE只保留条件成立的笔记,SORT支持多字段,前一字段相同时用后一字段决胜:
TASK FROM #projects WHERE !completed SORT due ASC LIMIT 10这条查询把 projects 标签下所有笔记里的未完成任务汇成一份可交互的任务清单,按截止日期升序、只显示 10 条;在这里勾选任务,原笔记里的内容会同步更新。
分组与聚合
GROUP BY把多条笔记按同一字段值捆成一行,每行带一个rows数组存所有命中的笔记;rows.rating会自动取出每篇笔记的 rating,再交给average()、length()这类聚合函数。反方向的操作是FLATTEN,把一个数组拆成每元素一行,适合"一本多作者、按作者展开"的场景。大仓库里建议加LIMIT控制结果数量。
完整的命令语法见 docs/docs/queries/data-commands.md;如果习惯 SQL,文档里还单独有一页对比 DQL 与 SQL 的差异,值得先读。
按日期展示
CALENDAR把每条结果渲染成日历上某天的一个点,用来回答"这段时间笔记都在什么时间活跃":
Dataview CALENDAR 查询:每个圆点代表当天的一条笔记,点越密说明当天的笔记活动越多
用 DataviewJS 扩展查询语言不够用的部分
DQL 覆盖不了的场景——多重分组、自定义排版——可以换成 DataviewJS:在代码块里直接写 JavaScript,dv.pages()会把可查询的笔记变成 JS 对象数组。
for (let group of dv.pages("#book").where(p => p["time-read"].year == 2021).groupBy(p => p.genre)) { dv.header(3, group.key); dv.table(["Name", "Time Read", "Rating"], group.rows.sort(k => k.rating, 'desc') .map(k => [k.file.link, k["time-read"], k.rating])); }这段代码把 2021 年读完的书按类型分成几个小节,每个小节内部再按评分排序:
DataviewJS 分组渲染效果:书籍按类型拆成 Dystopia、Nonfiction、Science Fiction 等四个表格,行内书名可跳转原文
有一个安全前提:DataviewJS 以插件权限运行,可以创建、修改文件;而普通dataview查询是沙箱化、只读的。所以只写自己看得懂的 JS,别人的脚本先审一遍再用。
查询查不到结果时的排查与第一步
问:查询会改动我的笔记吗?普通dataview查询是只读的;唯一会写回的是 TASK 清单里的勾选,它更新的是笔记里任务本身的内容。
问:查询返回空结果,怎么排查?三步走:先用LIST FROM <源>确认能取到笔记;再输出一列file.tags看标签是否真的存在;最后用typeof(rating)验证字段类型。空结果多半出在字段名拼写——含空格的字段名会自动规范成小写加连字符(如Basic Field变成basic-field),查询里必须用规范后的名字。
问:加完字段查询不到?索引随文件变化更新,不用等。查不到的先检查语法:行内字段是双冒号::,前置元数据是单冒号,两者不要混用。
现在就能做的第一步:挑一个 5 到 10 篇笔记的文件夹,给每篇补上rating、due之类的字段,再把上面TABLE示例里的文件夹名换成它——表格渲染出来的那一刻,整套流程就跑通了。
【免费下载链接】obsidian-dataviewA data index and query language over Markdown files, for https://obsidian.md/.项目地址: https://gitcode.com/gh_mirrors/ob/obsidian-dataview
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考