[Obsidian/可视化/插件] Obsidian Dataview 插件: 把 Markdown 笔记变成可查询数据库 —— DQL 与 JavaScript 双引擎驱动的动态视图插件
0 序言
- 最近刷到世界知名的AI博主 Karpathy 的 LLM Wiki 项目,阅读了这篇文章,其中提到了 Obsidian 的 Dataview 插件,为此了解了解。
LLM Wiki是由前 Tesla AI总监、OpenAI创始成员Andrej Karpathy 于2026年4月提出的一种个人知识库构建与管理范式、规约、愿景、最佳实践。
[知识库/知识管理] LLM Wiki:面向个人与小型团队的、LLM 驱动的编译型结构化知识库 | 个人知识库构建与管理范式 - 博客园/数据知音
Astro-Han/karpathy-llm-wiki(主流开源实现,Agent Skills 标准实现,社区最活跃)
karpathy/llm-wiki.md - github LLM Wiki 的发起 Repo:

- 内容提要:Obsidian DataView 插件的核心特性
- 数据库化:将 Vault 中所有笔记的元数据(YAML + 行内字段 + 隐式字段)构建为实时索引
- 双引擎:DQL 声明式查询(覆盖 90% 常规需求)+ DataviewJS 编程 API(无限扩展)
- 动态视图:TABLE / LIST / TASK / CALENDAR 四种输出,结果实时刷新、支持交互
1 概述: Obsidian Dataview 插件
插件效果

产品介绍
-
Obsidian Dataview 是一款将 Obsidian 知识库(Vault)视为可查询数据库的第三方社区插件。它通过解析 Markdown 文件中的元数据(YAML Frontmatter 与行内字段),构建实时索引,并提供类 SQL 的查询语言(DQL)和完整的 JavaScript API,让用户能够对笔记数据进行筛选、排序、分组、聚合与可视化展示。
-
产品定位:Obsidian 生态中最流行、功能最强大的结构化数据查询与动态视图插件
-
诞生背景:Obsidian 原生仅支持静态 Markdown 笔记与简单搜索,用户缺乏对笔记元数据进行结构化查询、自动汇总和动态仪表盘的能力。Dataview 填补了这一空白,使笔记从"静态文档"升级为"可查询的数据记录"
-
解决的核心问题:
- 跨笔记的元数据自动汇总(如读书清单、项目进度、任务看板)
- 基于条件的动态筛选与排序(无需手动维护列表)
- 任务的集中管理与状态追踪
- 自定义仪表盘与数据可视化
-
URL:
发展历程
| 时间 | 版本 | 关键事件 |
|---|---|---|
| 2021-01-31 | 首次发布 | 正式登陆 Obsidian 社区插件市场,作者 Michael Brenan(blacksmithgu) |
| 2021 年 | 0.3.x ~ 0.4.x | 快速迭代期,确立 DQL 语法、四种查询类型(TABLE/LIST/TASK/CALENDAR)、DataviewJS API |
| 2022 年 | 0.4.19 ~ 0.4.26 | 新增 CALENDAR 查询视图、任务子任务支持、多行任务、时区支持、性能优化 |
| 2023 年 | 0.5.x | 引入 IndexedDB 元数据缓存(0.5.19),大幅提升大型知识库启动速度;持续优化 Live Preview 渲染 |
| 2024 年 | 0.5.4x ~ 0.5.6x | 维护期,重点修复 Live Preview 列表渲染、文档完善、新增辅助函数 |
| 2025-03-16 | 0.5.68(稳定版) | 大量文档修复、Live Preview 列表渲染修复、新增/文档化函数 |
| 2025-04-07 | 0.5.70(Beta) | 尝试修复 #2557 问题,后续维护节奏放缓 |
维护状态说明:截至 2026 年 8 月,Dataview 的稳定版仍为 0.5.68,Beta 版停留在 0.5.70。
原作者 blacksmithgu 逐步减少投入,社区贡献者(如 holroy)参与维护。
尽管更新频率降低,但插件功能已高度成熟,社区生态(教程、示例、衍生插件)极为丰富,仍是 Obsidian 数据查询领域的事实标准。
核心功能 *
-
4种查询模式
- DQL(Dataview Query Language):流水线式、类 SQL 的声明式查询语言,覆盖 90% 常规需求
- Inline DQL:在 Markdown 正文中嵌入单行 DQL 表达式,预览模式下自动求值(如
`= this.file.name`) - DataviewJS:完整的 JavaScript API,可访问索引数据、执行复杂逻辑、自定义渲染,是高级用户的"逃生舱"
- Inline JS:在正文中嵌入单行 JavaScript 表达式(如
`$= dv.current().file.mtime`)
-
4种查询输出类型
- TABLE:表格视图,每行一条结果(1行即1个文件),每列一个字段
- LIST:无序列表视图,可附带一个字段
- TASK:交互式任务列表,支持勾选完成、按文件分组
- CALENDAR:日历视图,以圆点标记匹配日期的笔记
-
元数据采集
- 解析 YAML Frontmatter(文件顶部
---包裹的键值对) - 解析 行内字段(
Key:: Value语法,Dataview 独创) - 自动生成 隐式字段(文件名、创建/修改时间、标签、入链/出链、任务列表等,统一挂载在
file.*下)
- 解析 YAML Frontmatter(文件顶部
-
丰富的数据命令
FROM:按文件夹、标签、链接限定数据源WHERE:按字段条件过滤SORT:按字段排序(升序/降序)GROUP BY:按字段分组LIMIT:限制结果数量FLATTEN:将多值字段拆分为多行
-
内置函数库:字符串处理、日期运算、数学计算、类型转换、列表操作等数十个函数
-
自定义视图(Custom Views):通过
dv.view()加载独立的 JS 视图文件,实现复杂 UI 组件复用
核心优势
- 零侵入、纯文本:所有元数据存储在标准 Markdown 的 YAML Frontmatter 或行内字段中,不依赖专有格式,数据完全属于用户,可被任何文本编辑器读取
- 实时动态更新:索引在后台自动维护,笔记修改后查询结果即时刷新,无需手动刷新或重新生成
- 学习曲线平缓:DQL 语法接近 SQL,有数据库基础的用户可快速上手;即使零基础,通过
TABLE ... FROM ...的简单模式也能立即产出结果 - JavaScript 无限扩展:DataviewJS 提供完整编程能力,理论上可实现任意复杂的数据处理与自定义渲染,这是多数竞品不具备的
- 社区生态庞大:作为 Obsidian 下载量最高的插件之一,拥有海量教程、示例仓库、论坛讨论和衍生插件(如 Dataview Query Builder 可视化工具)
- 与 Obsidian 深度集成:原生支持 Wiki 链接、标签、任务、书签等 Obsidian 核心概念,查询结果中的链接可直接点击跳转
主要短板
- 维护节奏放缓:原作者投入减少,稳定版自 2025 年 3 月后未更新,部分长期存在的 Issue(如 #2557)未完全修复
- 大型知识库性能问题:在超过数千篇笔记的 Vault 中,全库扫描查询可能导致卡顿;虽有 IndexedDB 缓存缓解,但未加
FROM限定的查询仍可能较慢 - DQL 表达能力有限:复杂逻辑(如多表关联、子查询、窗口函数)无法用 DQL 表达,必须 resort 到 DataviewJS,提高了高级用法的门槛
- 无原生编辑能力:查询结果默认是只读视图,不能直接在表格中编辑元数据(需配合其他插件或 DataviewJS 实现)
- 行内字段语法非标准:
Key:: Value是 Dataview 独创语法,在其他 Markdown 编辑器中会原样显示为文本,存在一定的锁定风险 - 调试体验一般:DQL 报错信息不够友好,语法错误时定位困难;DataviewJS 调试需依赖 Obsidian 开发者控制台
局限性
- 仅支持 Markdown 文件:无法查询 PDF、图片、Office 文档等非 Markdown 附件的内容元数据
- 无持久化存储:查询结果是动态计算的,不会写回文件;如需保存快照需手动导出
- 不支持跨 Vault 查询:索引范围限定在当前打开的知识库内
- 移动端性能受限:在手机/平板等移动设备上,复杂 DataviewJS 查询可能明显卡顿
- 安全风险:DataviewJS 可执行任意 JavaScript,若从不可信来源复制脚本存在安全隐患(插件设置中可禁用 JS 查询)
适用场景
- 读书笔记管理:自动汇总所有书籍的书名、作者、评分、阅读状态,按评分排序或按类型分组
- 项目管理仪表盘:集中展示所有进行中项目的进度、截止日期、负责人,自动过滤已完成项目
- 任务追踪:跨笔记收集所有未完成任务,按优先级/截止日期排序,支持直接勾选完成
- 日记/周报自动生成:从每日笔记中提取关键数据(完成任务数、学习时长等),自动生成周报
- 内容资产盘点:统计知识库中各类型笔记数量、标签分布、最近修改的文件
- 会议纪要管理:按日期/项目/参会人筛选会议记录,自动生成待办事项汇总
- 学习进度追踪:跟踪课程/书籍的章节完成情况,计算整体进度百分比
同类竞品
| 竞品 | 类型 | 核心特点 | 与 Dataview 的差异 |
|---|---|---|---|
| Obsidian Bases | 官方核心插件(2025 年推出) | Notion 风格的数据库视图,支持表格/卡片布局,可视化筛选排序,可直接编辑属性 | 官方原生、零代码、可编辑,但无查询语言和 JS API,复杂逻辑能力弱;目前视图类型较少 |
| Projects | 第三方插件 | 基于文件夹的项目管理,支持表格/看板/日历/日历时间线等多视图 | 更侧重项目管理场景,UI 更友好,但查询灵活性不如 Dataview |
| DB Folder | 第三方插件 | 将文件夹变为 Notion 式数据库,支持多种列类型、公式、关联 | 可直接在视图中编辑数据,适合结构化数据管理,但缺乏全局查询能力 |
| Notion Bases for Obsidian | 第三方插件 | 7 种视图、18 种列类型、公式、关联、汇总、子任务,纯 Markdown 存储 | 功能最接近 Notion,视图丰富,但社区成熟度和生态远不如 Dataview |
| DataCards | 第三方插件 | 卡片式数据展示,支持看板视图 | 侧重可视化卡片展示,查询能力较弱 |
选型建议:如果你需要灵活的全局查询、复杂的数据处理、自定义仪表盘,Dataview 仍是首选;如果你更看重可视化操作、直接编辑、Notion 式体验,可以尝试 Obsidian Bases 或 Notion Bases for Obsidian。两者并非互斥,很多用户同时使用 Dataview(用于复杂查询)和 Bases(用于日常数据编辑)。
发展趋势
- 官方 Bases 的竞争压力:Obsidian 官方在 2025 年推出核心插件 Bases,提供了可视化的数据库视图,对 Dataview 的基础使用场景(表格展示、筛选排序)形成直接竞争。
未来普通用户可能更多转向 Bases,而 Dataview 将更聚焦于需要编程能力的高级用户
- 维护模式转变:从原作者主导开发转向社区维护模式,功能迭代放缓但稳定性持续提升
- 与 AI 工作流结合:越来越多用户将 Dataview 与 AI 插件(如 Smart Connections、Copilot)结合,用 Dataview 结构化数据作为 AI 的上下文输入
- 衍生工具生态:出现了 Dataview Query Builder(可视化 DQL 生成器)、Dataview to Properties(元数据迁移工具)等周边工具
- 元数据标准化趋势:Obsidian 原生 Properties(属性)功能的完善,使用户更多使用标准 YAML Frontmatter 而非 Dataview 行内字段,这有利于数据的可移植性
总结:Dataview 已进入成熟稳定期,虽然面临官方 Bases 的竞争,但其不可替代的 JavaScript API 和庞大社区生态使其在可预见的未来仍将是 Obsidian 高级数据查询的首选工具。
2 工作原理与架构
概念术语
| 术语 | 说明 |
|---|---|
| Vault(知识库) | Obsidian 管理的根文件夹,包含所有 Markdown 笔记和附件。Dataview 的索引范围限定在当前 Vault 内 |
| Metadata(元数据) | 描述笔记的数据,包括用户自定义的字段和 Dataview 自动生成的隐式字段 |
| Frontmatter(前置元数据) | Markdown 文件顶部用 --- 包裹的 YAML 格式键值对,是 Obsidian 标准的元数据存储方式 |
| Inline Field(行内字段) | Dataview 独创的元数据语法,格式为 Key:: Value,可写在笔记正文中任意位置 |
| Implicit Field(隐式字段) | Dataview 自动为每个文件生成的元数据,如文件名、创建时间、标签、链接等,统一通过 file.* 访问 |
| DQL(Dataview Query Language) | Dataview 的声明式查询语言,语法类似 SQL,采用流水线式的子句组合 |
| DataviewJS | Dataview 的 JavaScript API,在 dataviewjs 代码块中执行,通过全局 dv 对象访问索引和渲染工具 |
| Query Type(查询类型) | 决定查询输出格式的关键字,包括 TABLE、LIST、TASK、CALENDAR 四种 |
| Data Command(数据命令) | 查询中用于限定、过滤、排序、分组的子句,包括 FROM、WHERE、SORT、GROUP BY、LIMIT、FLATTEN |
| Source(数据源) | FROM 子句的参数,用于限定查询范围,可以是文件夹路径、标签、链接表达式 |
| Index(索引) | Dataview 在后台维护的元数据数据库,存储所有文件的解析结果,基于 IndexedDB 持久化缓存 |
| Custom View(自定义视图) | 通过 dv.view() 加载的独立 JS 文件,可封装复杂的渲染逻辑并在多处复用 |
架构与运行原理
Dataview 的整体架构可分为数据采集层、索引存储层、查询引擎层、渲染展示层四个部分:
2.2.1 数据采集层
Dataview 在 Obsidian 启动时和文件变更时,对 Vault 中的每个 Markdown 文件进行解析:
- YAML Frontmatter 解析:读取文件顶部
---之间的 YAML 内容,将每个键值对转化为字段。支持嵌套对象(通过.访问)和数组 - 行内字段解析:扫描正文,匹配
Key:: Value模式的行内字段。支持三种写法:- 独立行:
Key:: Value - 方括号包裹:
[Key:: Value](可隐藏键名显示) - 圆括号包裹:
(Key:: Value)(键名和值都隐藏,仅用于数据存储)
- 独立行:
- 隐式字段生成:为每个文件自动生成
file.*系列字段,包括文件名、路径、创建/修改时间、标签列表、入链/出链列表、任务列表、列表元素等
2.2.2 索引存储层
- 元数据索引引擎:核心组件,负责调度文件解析、维护索引一致性。通过监听 Obsidian 的文件创建、修改、删除、重命名事件,实时更新索引
- 内存索引:所有已解析文件的元数据存储在内存中,供查询引擎快速访问。Vault 打开时全量构建,之后增量更新
- IndexedDB 缓存:自 0.5.19 版本引入,将解析后的元数据持久化到浏览器的 IndexedDB 中。下次启动时优先从缓存加载,再增量校验变更,大幅缩短大型 Vault 的启动时间
2.2.3 查询引擎层
- DQL 解析器:基于
parsimmon(解析器组合子库)构建,将 DQL 文本解析为抽象语法树(AST)。DQL 采用流水线式设计,每个数据命令(FROM/WHERE/SORT 等)依次对数据集进行变换 - 查询执行器:遍历 AST,从索引中获取数据,依次应用过滤、排序、分组、扁平化、限制等操作,最终生成结果集
- DataviewJS API:提供
dv全局对象,直接暴露索引数据(如dv.pages()、dv.page())和渲染方法(如dv.table()、dv.list()、dv.taskList()),用户可编写任意 JavaScript 逻辑处理数据
2.2.4 渲染展示层
- 基于 Preact(轻量级 React 替代库)构建 UI 组件
- 四种查询类型对应四种渲染组件:TABLE(表格)、LIST(列表)、TASK(交互式任务列表)、CALENDAR(日历)
- 渲染结果嵌入 Obsidian 的阅读模式和 Live Preview 模式中
- TASK 视图支持交互:点击复选框可直接修改源文件中的任务状态
- 支持 Obsidian 主题样式,可通过 CSS 自定义外观
2.2.5 关键技术依赖
| 依赖库 | 用途 |
|---|---|
| luxon | 日期与时间处理,提供 DateTime、Duration 等类型 |
| parsimmon | 解析器组合子库,用于构建 DQL 语法解析器 |
| preact | 轻量级 React 替代,用于构建查询结果的 UI 组件 |
| localforage | 客户端存储封装,IndexedDB 缓存的底层依赖 |
| @codemirror/* | 代码编辑器集成,为 dataview/dataviewjs 代码块提供语法高亮 |
| papaparse | CSV 数据处理(辅助功能) |
3 使用指南
3.1 安装部署
3.1.1 通过 Obsidian 社区插件市场安装(推荐)
- 打开 Obsidian → 设置(Settings)→ 第三方插件(Community plugins)
- 关闭"安全模式"(Safe mode)(首次使用第三方插件时)
- 点击"浏览"(Browse),搜索 Dataview
- 点击"安装"(Install),安装完成后点击"启用"(Enable)
3.1.2 手动安装(适用于无法访问插件市场的环境)
- 从 GitHub Releases 下载最新版本的三个文件:
main.js、manifest.json、styles.css - 在 Vault 的插件目录下创建文件夹:
<Vault根目录>/.obsidian/plugins/dataview/ - 将三个文件放入该文件夹
- 重启 Obsidian,在 设置 → 第三方插件 中启用 Dataview
3.1.3 关键设置项
安装后进入 设置 → Dataview,可配置以下选项:
| 设置项 | 说明 | 推荐值 |
|---|---|---|
| Enable JavaScript Queries | 是否允许执行 dataviewjs 代码块 |
高级用户开启;安全敏感场景可关闭 |
| Enable Inline JavaScript Queries | 是否允许执行行内 JS 表达式($= ...) |
同上 |
| Enable Inline Field Highlighting | 是否高亮显示行内字段(Key:: Value) |
开启,便于识别元数据 |
| Inline Field Prefix | 行内字段前缀字符 | 默认 :: |
| Wikilink Target Columns | 表格中哪些列自动渲染为 Wiki 链接 | 默认开启 |
| Recursive Tag/Subtag Matching | 标签是否递归匹配子标签(如 #book 匹配 #book/fiction) |
开启 |
元数据标注(数据准备)(必读)
在使用查询之前,需要先为笔记添加元数据。Dataview 支持三种元数据来源。
3.2.1 YAML Frontmatter
在文件顶部用 --- 包裹的 YAML 键值对:
---
title: "深入理解计算机系统"
author: "Randal E. Bryant"
rating: 9
status: "reading"
tags:
- book
- computer-science
publish-date: 2021-03-01
pages: 1120
---
支持的数据类型:
- 文本(字符串):
author: "Randal E. Bryant" - 数字:
rating: 9、pages: 1120 - 布尔值:
reviewed: true - 日期:
publish-date: 2021-03-01(ISO 格式自动识别为日期类型) - 数组/列表:
tags: [book, computer-science]或多行格式 - 嵌套对象:
metadata: { rating: 9, reviewed: false }(通过metadata.rating访问)
3.2.2 行内字段(Inline Fields)
在笔记正文中任意位置使用 Key:: Value 语法:
# 读书笔记
**书名**:: 深入理解计算机系统
**作者**:: Randal E. Bryant
**评分**:: 9
**状态**:: reading
这是一本经典的计算机系统教材。
也可以在行内使用:我最近在读 [书名:: 深入理解计算机系统],感觉 [难度:: 较高]。
如果想完全隐藏字段:(完成度:: 60%)
3种行内字段写法对比:
| 写法 | 渲染效果 | 适用场景 |
|---|---|---|
Key:: Value |
显示为 "Key:: Value"(带高亮) | 需要在正文中同时展示键和值 |
[Key:: Value] |
仅显示 "Value"(键隐藏) | 需要展示值但不显示键名 |
(Key:: Value) |
键和值都不显示(完全隐藏) | 仅用于存储数据,不希望在阅读时看到 |
3.2.3 隐式字段(Implicit Fields)
- Dataview 自动为每个文件生成,无需手动标注,通过
file.*访问:
| 字段 | 类型 | 说明 |
|---|---|---|
file.name |
文本 | 文件名(不含扩展名) |
file.folder |
文本 | 所在文件夹路径 |
file.path |
文本 | 完整文件路径(含文件名) |
file.ext |
文本 | 文件扩展名,通常为 md |
file.link |
链接 | 指向该文件的 Wiki 链接 |
file.size |
数字 | 文件大小(字节) |
file.ctime |
日期时间 | 文件创建时间 |
file.cday |
日期 | 文件创建日期 |
file.mtime |
日期时间 | 文件最后修改时间 |
file.mday |
日期 | 文件最后修改日期 |
file.tags |
列表 | 所有标签(含子标签展开,如 #a/b 展开为 #a, #a/b) |
file.etags |
列表 | 所有显式标签(不展开子标签) |
file.inlinks |
列表 | 所有指向本文件的链接(入链) |
file.outlinks |
列表 | 本文件中所有向外的链接(出链) |
file.aliases |
列表 | 文件的别名(来自 Frontmatter 的 aliases) |
file.tasks |
列表 | 文件中所有任务(- [ ] / - [x]) |
file.lists |
列表 | 文件中所有列表元素(含任务) |
file.day |
日期 | 仅当文件名含日期(如 2026-08-22)或有 date 字段时可用 |
file.starred |
布尔 | 是否被 Obsidian 书签插件收藏 |
DQL 查询语法详解
3.3.1 查询的基本结构 *
每个 DQL 查询遵循以下流水线结构:
<QUERY-TYPE> <字段列表>
FROM <数据源>
<数据命令>
<数据命令>
...
- QUERY-TYPE(必填):TABLE / LIST / TASK / CALENDAR 之一
- FROM(可选):限定数据源,只能出现一次,且必须紧跟在 QUERY-TYPE 之后
- 其他数据命令(可选,可多次、任意顺序):WHERE / SORT / GROUP BY / LIMIT / FLATTEN
3.3.2 查询类型(Query Type): TABLE / LIST / TASK / CALENDAR
TABLE — 表格视图
最常用的查询类型,以表格形式展示结果:
TABLE 字段1, 字段2 AS "别名", 计算表达式
FROM 数据源
示例:
TABLE file.name AS "书名", author AS "作者", rating AS "评分", status AS "状态"
FROM "books" //目录 = "books"
WHERE rating >= 8
SORT rating DESC
无字段 TABLE:TABLE WITHOUT ID 可隐藏默认的第一列(文件链接列):
TABLE WITHOUT ID title AS "书名", rating AS "评分"
FROM #book //含有 book 的 tags 的文件
LIST — 列表视图
以无序列表形式展示匹配的文件,可附带一个字段:
LIST 字段
FROM 数据源
示例:
LIST "评分:" + rating
FROM #book
WHERE status = "reading"
SORT rating DESC
TASK — 任务视图
以交互式任务列表展示,支持直接勾选完成:
TASK
FROM 数据源
WHERE 条件
示例:
TASK
FROM #projects/active
WHERE !completed
GROUP BY file.link
TASK 查询的结果是任务项(对应源文件的
- [] xxx text行)而非文件,因此WHERE中可直接使用任务的字段(如completed、due、priority),以及file.*来访问任务所在文件的元数据。
CALENDAR — 日历视图
简介
- 以月历形式展示,每个匹配的笔记在对应日期上显示一个圆点:
CALENDAR 日期字段
FROM 数据源
WHERE <过滤条件>
- 与 TABLE/LIST/TASK 不同,CALENDAR 的日期字段是必填的—— 日历需要知道每条结果对应哪一天
- 示例:
以笔记的创建日期(
file.cday)为坐标,将 Vault 中所有笔记渲染到月历上,有笔记的日期显示圆点。
CALENDAR file.cday
FROM "diaryDir"
SORT file.cday desc
检索逻辑(执行流程)
- 逐步拆解:
| 步骤 | 说明 |
|---|---|
| ① 筛选文件集合 | 先通过 FROM(文件夹 / 标签 / 链接)和 WHERE(字段条件)筛选出符合条件的笔记,与其他查询类型完全一致 |
| ② 提取日期字段 | 对筛选出的每篇笔记,读取 CALENDAR 关键字后指定的字段值。该值必须是日期类型(date),否则该条记录会被丢弃 |
| ③ 按日期分组 | 将所有笔记按日期值分组。同一天的多篇笔记归为同一组 |
| ④ 渲染月历 | 输出标准月历视图(月 / 周切换),有匹配笔记的日期显示圆点;同一天有多篇笔记时,圆点会堆叠显示(多个圆点纵向排列) |
日期字段的来源x3种
- 隐式字段(最常用)
| 字段 | 含义 |
|---|---|
| file.cday | 文件创建日期 |
| file.mday | 文件最后修改日期 |
| file.day | 仅当文件名含日期(如 2026-08-22.md)或 Frontmatter 有 date 字段时可用 |
- 自定义 Frontmatter 日期字段
---
due: 2026-09-15
birthday: 1990-05-20
publish-date: 2026-08-01
---
对应的 dataview
CALENDAR due
FROM #task
WHERE !completed
- 计算 / 转换后的日期
如果日期存储为字符串,需用 date() 函数转换:
CALENDAR date(due_str)
FROM "projects"
也可以对日期做简单运算:
CALENDAR due - dur(7 days)
FROM #task
在截止日期前 7 天的位置显示提醒圆点。
关键注意事项
| 问题 | 说明 |
|---|---|
| 日期字段为 null 会怎样? | 该条记录不会显示在日历上。建议加 WHERE 日期字段 过滤掉无日期的记录,虽然不加也能自动跳过,但显式写出更清晰 |
| 日期时间类型(DateTime)呢? | 只取日期部分,时间部分被忽略。如 file.ctime(含时分秒)也可正常用于 CALENDAR |
| 同一天多篇笔记怎么显示? | 圆点会堆叠,纵向排列多个圆点。鼠标悬停可看到具体文件 |
| 能自定义圆点颜色吗? | DQL 层面不支持,圆点颜色由当前 Obsidian 主题决定。如需自定义颜色,需用 DataviewJS 或 CSS 片段(.dataview-calendar-dot) |
| 能显示多个日期字段吗? | 不能,一个 CALENDAR 查询只能指定一个日期字段。如需同时看创建日和修改日,需写两个独立的 CALENDAR 代码块 |
| 点击圆点会怎样? | 点击日期或圆点会跳转到对应笔记(如果当天只有一篇)或显示该天的文件列表 |
| 支持周视图吗? | 支持,日历视图右上角可切换月 / 周视图 |
| 性能如何? | CALENDAR 本身渲染开销不大,但如果 FROM 不限定范围、全库扫描,在大 Vault 中仍可能较慢。建议始终加 FROM 限定 |
3.3.3 FROM — 数据源限定
FROM 用于限定查询的文件范围,支持以下数据源类型:
| 数据源类型 | 语法 | 说明 |
|---|---|---|
| 文件夹 | FROM "路径" |
查询指定文件夹及其子文件夹下的所有文件 |
| 标签 | FROM #标签 |
查询包含指定标签的文件 |
| 入链 | FROM [[文件名]] |
查询链接到指定文件的所有文件 |
| 出链 | FROM outgoing([[文件名]]) |
查询指定文件中链接到的所有文件 |
组合表达式:支持 AND、OR、NOT 和括号组合:
-- 标签或文件夹
FROM #book OR "books"
-- 同时满足标签和文件夹
FROM #book AND "books/fiction"
-- 排除某文件夹
FROM #book AND -"books/archived"
-- 复杂组合
FROM (#assignment AND "30 School") OR ("30 School/32 Homeworks" AND outgoing([[School Dashboard]]))
文件夹路径前加
-表示排除,如FROM -"templates"排除模板文件夹。
3.3.4 WHERE — 条件过滤
WHERE 用于按字段条件过滤结果,支持比较运算符和逻辑运算符:
比较运算符:=、!=、<、>、<=、>=
逻辑运算符:AND、OR、NOT(或 !)
示例:
TABLE title, rating, status
FROM #book
WHERE rating >= 8 AND status = "completed"
LIST
WHERE due AND due < date(today)
TABLE title, author
FROM #book
WHERE contains(tags, "科幻") OR contains(author, "刘慈欣")
常用过滤模式:
- 字段存在性检查:
WHERE rating(rating 字段存在且非空) - 字段不存在:
WHERE !rating或WHERE rating = null - 文本包含:
WHERE contains(title, "算法") - 列表包含:
WHERE contains(tags, "#book") - 日期比较:
WHERE due > date(today) - 正则匹配:
WHERE regexmatch("^A", title)
3.3.5 SORT — 排序
SORT 字段 [ASC|DESC]
ASC:升序(默认)DESC:降序
示例:
TABLE title, rating, file.mtime
FROM #book
SORT rating DESC, file.mtime ASC
支持多字段排序,先按第一个字段排序,相同则按第二个字段排序。
3.3.6 GROUP BY — 分组
将结果按指定字段分组,每组生成一行。分组后,组内数据通过 rows 关键字访问:
TABLE rows.file.link AS "书籍", length(rows) AS "数量"
FROM #book
GROUP BY genre
示例:
TABLE length(rows) AS "书籍数量", average(rows.rating) AS "平均评分"
FROM #book
GROUP BY genre
SORT length(rows) DESC
3.3.7 LIMIT — 限制结果数
LIMIT 数字
示例:
TABLE title, rating
FROM #book
SORT rating DESC
LIMIT 10
3.3.8 FLATTEN — 扁平化
将多值字段(如数组、列表)拆分为多行,每行一个值:
FLATTEN 字段 AS 别名
示例:
TABLE file.name AS "文件", L AS "列表项"
FROM "dailys"
FLATTEN file.lists AS L
WHERE contains(L.text, "重要")
TABLE file.name AS "书名", tag AS "标签"
FROM #book
FLATTEN tags AS tag
3.3.9 表达式与函数
运算符
| 类别 | 运算符 | 说明 |
|---|---|---|
| 算术 | + - * / % |
加减乘除取模 |
| 比较 | = != < > <= >= |
比较运算 |
| 逻辑 | AND OR NOT / ! |
逻辑运算 |
| 字符串 | + |
字符串拼接 |
| 列表 | + |
列表合并 |
常用函数
字符串函数:
| 函数 | 说明 | 示例 |
|---|---|---|
lower(x) |
转小写 | lower("Hello") = "hello" |
upper(x) |
转大写 | upper("Hello") = "HELLO" |
length(x) |
字符串/列表长度 | length("abc") = 3 |
contains(haystack, needle) |
是否包含 | contains("hello", "ell") = true |
startswith(s, prefix) |
是否以...开头 | startswith("abc", "a") = true |
endswith(s, suffix) |
是否以...结尾 | endswith("abc", "c") = true |
replace(s, pattern, replacement) |
替换 | replace("a-b", "-", "_") = "a_b" |
regexmatch(pattern, s) |
正则匹配 | regexmatch("^\\d+$", "123") = true |
trim(s) |
去除首尾空白 | trim(" abc ") = "abc" |
substring(s, start, end) |
截取子串 | substring("abcde", 1, 3) = "bc" |
日期函数:
| 函数 | 说明 | 示例 |
|---|---|---|
date(any) |
转换为日期 | date("2026-08-22") |
date(today) |
今天日期 | date(today) |
date(tomorrow) |
明天日期 | date(tomorrow) |
date(yesterday) |
昨天日期 | date(yesterday) |
duration(any) |
转换为时长 | duration("7 days") |
day(x) |
获取日期中的日 | day(date("2026-08-22")) = 22 |
month(x) |
获取月份 | month(date("2026-08-22")) = 8 |
year(x) |
获取年份 | year(date("2026-08-22")) = 2026 |
hour(x) |
获取小时 | 用于日期时间类型 |
数学函数:
| 函数 | 说明 |
|---|---|
round(x) |
四舍五入 |
floor(x) |
向下取整 |
ceil(x) |
向上取整 |
min(a, b) / max(a, b) |
最小/最大值 |
sum(list) |
列表求和 |
average(list) |
列表平均值 |
min(list) / max(list) |
列表最小/最大值 |
类型与其他函数:
| 函数 | 说明 |
|---|---|
typeof(x) |
返回值的类型(string/number/boolean/date/link/list/object/null) |
number(x) |
转换为数字 |
string(x) |
转换为字符串 |
link(path, [display]) |
创建链接 |
embed(link) |
创建嵌入链接(![[...]]) |
elink(url, [display]) |
创建外部链接 |
nonnull(list) |
过滤列表中的 null 值 |
object(k1, v1, ...) |
创建对象 |
array(...) |
创建数组 |
3.3.10 行内 DQL 查询(Inline DQL)
在 Markdown 正文中使用反引号包裹,以 = 开头:
当前笔记名称:`= this.file.name`
当前笔记创建于:`= this.file.cday`
本书评分:`= this.rating`
距离截止日期还有:`= this.due - date(today)`
this关键字引用当前笔记的元数据- 行内查询在阅读模式/Live Preview 下自动求值并显示结果
- 支持所有 DQL 表达式和函数
DataviewJS 进阶用法
3.4.1 基本结构
在 dataviewjs 代码块中编写 JavaScript,通过全局 dv 对象访问 API:
// 获取所有带 #book 标签的页面
const books = dv.pages("#book");
// 渲染表格
dv.table(
["书名", "作者", "评分"],
books
.where(b => b.rating >= 8)
.sort(b => b.rating, "desc")
.map(b => [b.file.link, b.author, b.rating])
);
3.4.2 核心 API
数据获取
| API | 说明 |
|---|---|
dv.pages(source?) |
获取匹配数据源的所有页面(返回 Page 数组),如 dv.pages("#book")、dv.pages('"folder"') |
dv.page(path) |
获取指定路径的单个页面 |
dv.current() |
获取当前代码块所在的页面 |
渲染方法
| API | 说明 |
|---|---|
dv.table(headers, values) |
渲染表格,headers 为列名数组,values 为二维数组 |
dv.list(elements) |
渲染无序列表 |
dv.taskList(tasks, groupByFile?) |
渲染交互式任务列表,groupByFile 默认为 true |
dv.header(level, text) |
渲染标题 |
dv.paragraph(text) |
渲染段落 |
dv.el(tag, text, options?) |
渲染自定义 HTML 元素 |
dv.view(path, input?) |
加载并渲染自定义视图 |
工具方法
| API | 说明 |
|---|---|
dv.date(any) |
解析为日期对象 |
dv.duration(any) |
解析为时长对象 |
dv.array(value) |
确保值为数组 |
dv.isLink(value) |
判断是否为链接类型 |
dv.isDateTime(value) |
判断是否为日期时间类型 |
dv.isDuration(value) |
判断是否为时长类型 |
3.4.3 Page 对象的属性与方法
dv.pages() 返回的每个 Page 对象可直接访问元数据字段:
const page = dv.pages("#book").first();
// 自定义字段
page.title;
page.rating;
page.author;
// 隐式字段
page.file.name;
page.file.ctime;
page.file.tags;
page.file.tasks;
page.file.inlinks;
链式查询方法(类似 Lodash 的集合操作):
| 方法 | 说明 |
|---|---|
.where(predicate) |
过滤 |
.sort(comparator, direction?) |
排序,direction 为 "asc" 或 "desc" |
.groupBy(selector) |
分组,返回 { key, rows } 数组 |
.map(fn) |
映射转换 |
.flatMap(fn) |
扁平化映射 |
.limit(n) |
限制数量 |
.slice(start, end?) |
切片 |
.first() / .last() |
获取首/末元素 |
.length |
元素数量 |
3.4.4 实战示例
示例 1:带进度条的项目列表
const projects = dv.pages("#project").where(p => p.status === "active");
for (const project of projects) {
const tasks = project.file.tasks;
const completed = tasks.where(t => t.completed).length;
const total = tasks.length;
const percent = total > 0 ? Math.round((completed / total) * 100) : 0;
dv.header(4, project.file.link);
dv.el("div", `
<div style="background:#e0e0e0;border-radius:4px;height:8px;margin:4px 0;">
<div style="background:#4caf50;border-radius:4px;height:8px;width:${percent}%"></div>
</div>
<span style="font-size:0.85em;color:#666">${completed}/${total} 任务 (${percent}%)</span>
`);
}
示例 2:按项目分组的未完成任务
const tasks = dv.pages("#project").file.tasks.where(t => !t.completed);
const grouped = tasks.groupBy(t => t.file.link);
for (const group of grouped) {
dv.header(4, group.key);
dv.taskList(group.rows, false);
}
示例 3:最近 30 天完成任务统计
const allTasks = dv.pages().file.tasks;
const completed = allTasks.where(t => {
if (!t.completed) return false;
// 任务完成时间(如果有 completion 字段)
if (t.completion) {
return t.completion > dv.date("today").minus({ days: 30 });
}
return false;
});
dv.header(3, `最近 30 天完成 ${completed.length} 个任务`);
dv.taskList(completed, true);
示例 4:标签分布统计
const allPages = dv.pages();
const tagCount = {};
for (const page of allPages) {
for (const tag of page.file.tags) {
tagCount[tag] = (tagCount[tag] || 0) + 1;
}
}
const sorted = Object.entries(tagCount)
.sort((a, b) => b[1] - a[1])
.slice(0, 20);
dv.table(
["标签", "数量"],
sorted.map(([tag, count]) => [tag, count])
);
3.4.5 行内 JS 查询
在正文中使用反引号包裹,以 $= 开头:
本笔记最后修改于 `$= dv.current().file.mtime`
本知识库共有 `$= dv.pages().length` 篇笔记
当前项目进度:`$= Math.round(dv.current().file.tasks.where(t => t.completed).length / dv.current().file.tasks.length * 100)`%
3.4.6 自定义视图(Custom Views)
将复杂的 DataviewJS 逻辑封装为独立文件,通过 dv.view() 复用:
- 在 Vault 中创建视图文件夹,如
views/project-progress/ - 在其中创建
view.js:
// views/project-progress/view.js
const { project } = input;
const tasks = project.file.tasks;
const completed = tasks.where(t => t.completed).length;
const total = tasks.length;
const percent = total > 0 ? Math.round((completed / total) * 100) : 0;
dv.header(4, project.file.link);
dv.paragraph(`进度:${completed}/${total} (${percent}%)`);
- 在任意笔记中调用:
for (const project of dv.pages("#project")) {
dv.view("views/project-progress", { project });
}
常用查询模板
3.5.1 读书笔记管理
TABLE file.name AS "书名", author AS "作者", rating AS "评分", status AS "阅读状态"
FROM #book
SORT rating DESC
3.5.2 今日待办
TASK
FROM "diary"
WHERE !completed AND (due = date(today) OR contains(text, "今天"))
SORT priority DESC
3.5.3 逾期任务
TASK
WHERE !completed AND due AND due < date(today)
SORT due ASC
3.5.4 最近修改的笔记
TABLE file.mtime AS "修改时间", file.folder AS "位置"
FROM -"templates"
SORT file.mtime DESC
LIMIT 15
3.5.5 本月生日/纪念日
LIST birthday
FROM #contact
WHERE birthday AND month(birthday) = month(date(today))
SORT day(birthday) ASC
3.5.6 项目仪表盘(综合)
TABLE WITHOUT ID
file.link AS "项目",
status AS "状态",
priority AS "优先级",
due AS "截止日期",
length(file.tasks.where(t => !t.completed)) AS "待办数"
FROM #project
WHERE status != "archived"
SORT priority DESC, due ASC
Z FAQ
Q: Dataview 查询不显示结果怎么办?
首先检查以下几点:
- 语法错误:确认代码块语言标记为
dataview(而非dataviewjs),关键字拼写正确(TABLE、FROM、WHERE等) - 数据源路径:
FROM "文件夹路径"中的路径是否正确,路径相对于 Vault 根目录,区分大小写 - 字段名:
WHERE和TABLE中引用的字段名是否与 Frontmatter/行内字段中的键名完全一致(区分大小写) - 字段类型:比较运算时确保字段类型一致,如日期字段需用
date()转换后再比较 - 索引未更新:尝试重启 Obsidian 或在设置中触发"重新索引"(Reload Index)
- 查看控制台:按
Ctrl+Shift+I(Windows/Linux)或Cmd+Opt+I(Mac)打开开发者工具,查看 Console 中的报错信息
Q: 行内字段 Key:: Value 不被识别怎么办?
- 确认在 Dataview 设置中开启了 Enable Inline Field Highlighting
- 行内字段的
::前后可以有空格,但Key部分不能包含冒号 - 如果行内字段在标题行(如
## 标题 Key:: Value),可能不被解析,建议放在正文中 - 方括号写法
[Key:: Value]和圆括号写法(Key:: Value)中的字段同样会被索引 - 如果字段值包含特殊字符(如
::、#、[[]]),建议使用 YAML Frontmatter 存储
Q: 如何在查询结果中直接编辑数据?
Dataview 的 DQL 查询结果默认是只读的。如需直接编辑,有以下方案:
- 使用 Obsidian Bases:官方核心插件 Bases 支持在表格视图中直接编辑属性
- 使用 DB Folder 或 Notion Bases 插件:这些插件提供可编辑的数据库视图
- DataviewJS + 自定义 UI:通过 DataviewJS 编写自定义 HTML 表单,结合 Obsidian API 实现数据写回(难度较高)
- 点击链接跳转编辑:查询结果中的文件链接可点击跳转到源文件,在源文件中编辑 Frontmatter
Q: Dataview 和 Obsidian 官方 Bases 有什么区别?该选哪个?
| 维度 | Dataview | Obsidian Bases |
|---|---|---|
| 性质 | 第三方社区插件 | 官方核心插件 |
| 查询方式 | DQL 查询语言 + JavaScript API | 可视化筛选/排序,无查询语言 |
| 可编辑性 | 只读(DQL) | 可直接编辑属性 |
| 视图类型 | TABLE/LIST/TASK/CALENDAR | 表格/卡片(持续增加中) |
| 复杂逻辑 | 支持(通过 JS) | 不支持 |
| 学习成本 | 较高(需学 DQL/JS) | 低(可视化操作) |
| 全局查询 | 支持(跨文件夹/标签) | 基于文件夹/属性,范围较固定 |
建议:日常简单的数据展示和编辑用 Bases,需要复杂查询、自定义仪表盘、跨库汇总时用 Dataview。两者可以共存。
Q: 大型知识库中 Dataview 查询很慢怎么办?
优化策略:
- 始终使用
FROM限定范围:避免全库扫描,如FROM "books"或FROM #book - 减少查询数量:一个页面中不要放置过多 dataview 代码块
- 避免复杂的
WHERE计算:如在WHERE中使用正则、字符串处理等会降低性能 - 使用
LIMIT限制结果数:不需要展示全部结果时加上LIMIT - 禁用不必要的隐式字段索引:在设置中可关闭部分索引功能(如任务索引、列表索引)
- 考虑拆分 Vault:如果笔记数量超过数万篇,可考虑按主题拆分为多个 Vault
- 使用 IndexedDB 缓存:确保 Dataview 版本 >= 0.5.19,缓存功能默认开启
Q: DataviewJS 安全吗?可以随意复制网上的脚本吗?
不安全。DataviewJS 可执行任意 JavaScript 代码,拥有访问 Obsidian API、文件系统(通过 Obsidian API)、网络请求等权限。从不可信来源复制脚本存在以下风险:
- 窃取或篡改你的笔记数据
- 发送数据到外部服务器
- 执行恶意操作
安全建议:
- 只从可信来源(官方文档、知名社区、自己理解的代码)复制脚本
- 使用前仔细阅读代码,理解每一行的作用
- 在 Dataview 设置中可关闭 Enable JavaScript Queries 来禁用所有 JS 查询
- 对于简单需求,优先使用 DQL 而非 DataviewJS
Q: 如何查询任务的子任务?
Dataview 支持任务的层级关系。在 TASK 查询中:
- 每个任务对象有
children属性,包含其子任务列表 t.completed仅表示当前任务本身是否完成,不考虑子任务- 可通过
t.subtasks访问所有后代任务
TASK
FROM #project
WHERE !completed AND length(children) > 0
在 DataviewJS 中:
const tasks = dv.pages().file.tasks;
const parentTasks = tasks.where(t => t.children.length > 0);
dv.taskList(parentTasks, true);
Q: 日期比较不生效怎么办?
常见原因和解决方案:
- 字段不是日期类型:如果 Frontmatter 中日期写为
due: "2026-08-22"(带引号),会被识别为字符串而非日期。应去掉引号:due: 2026-08-22 - 比较时需转换:如果字段确实是字符串,在查询中用
date(due)转换后再比较:WHERE date(due) < date(today) - 日期格式:确保日期为 ISO 格式
YYYY-MM-DD,其他格式可能无法被正确识别 - 行内字段日期:行内字段中的日期同样需要符合 ISO 格式,如
due:: 2026-08-22
Q: 如何在 Dataview 中使用 CSS 自定义样式?
Dataview 的查询结果会被特定的 CSS 类包裹,可通过自定义 CSS 片段(CSS Snippets)修改样式:
- 在 Vault 的
.obsidian/snippets/目录下创建dataview-custom.css - 添加样式规则,常用选择器:
.dataview— 所有 Dataview 结果的外层容器.dataview.table-view-table— TABLE 视图的表格.dataview.table-view-table th— 表头.dataview.task-list-item— TASK 视图的任务项.dataview.list-view-ul— LIST 视图的列表
- 在 Obsidian 设置 → 外观 → CSS 代码片段 中启用该片段
示例:
/* 表格斑马纹 */
.dataview.table-view-table tr:nth-child(even) {
background-color: rgba(0, 0, 0, 0.05);
}
/* 表头加粗 */
.dataview.table-view-table th {
font-weight: 700;
}
Q: 如何导出 Dataview 查询结果?
Dataview 结果是动态渲染的,不会自动保存为文件。导出方式:
- 复制粘贴:在阅读模式下选中查询结果,复制为 Markdown 表格或纯文本
- 截图:使用截图工具保存为图片
- DataviewJS 导出:编写脚本将结果写入文件(通过 Obsidian API 的
vault.create()) - 打印为 PDF:使用 Obsidian 的"导出为 PDF"功能,包含查询结果的页面会被导出
- 配合其他插件:如使用 "Advanced Tables" 等插件辅助表格处理
Y 推荐文献
- Dataview 官方文档 - blacksmithgu.github.io
- Dataview GitHub 仓库
- Dataview Query Builder(可视化 DQL 生成器)
- Obsidian Dataview Cheatsheet(速查表) - seburbandev
- Dataview 插件官方文档中文版 - Obsidian 中文论坛
- Obsidian Dataview: The Complete Guide to Dynamic Dashboards and Queries - Obsibrain
- Obsidian Dataview for Beginners: Complete Guide - notes-automate.com
- DeepWiki: obsidian-dataview(代码级文档)
- Obsidian Bases 官方文档
- 《How to Take Smart Notes》- Sönke Ahrens(#,Zettelkasten 方法论,理解结构化笔记的基础)
- [知识库/知识管理] LLM Wiki:面向个人与小型团队的、LLM 驱动的编译型结构化知识库 | 个人知识库构建与管理范式 - 博客园/数据知音
- karpathy/llm-wiki.md - github
- Astro-Han/karpathy-llm-wiki(主流开源实现,Agent Skills 标准实现,社区最活跃)
X 参考文献
- Obsidian Dataview - GitHub
- Dataview 官方文档首页
- Structure of a Query - DQL 查询结构
- Metadata on Pages - 页面元数据
- Expressions - 表达式参考
- Functions - 函数参考
- Codeblock Reference - DataviewJS API 参考
- DataviewJS 概述
- DQL, JS and Inlines - 三种查询模式对比
- CHANGELOG - 版本更新日志
- Releases - 发布版本
- Obsidian Stats - Dataview 插件统计
- Obsidian Bases 官方介绍
- Notion Bases for Obsidian - GitHub
- Obsidian Dataview 表格视图教程 - CSDN
- Obsidian DataviewJS 实战 - CSDN
- Obsidian Dataview 表达式详解 - CSDN
- 3分钟掌握Obsidian Dataview 2025全功能 - CSDN
- Dataview插件官方文档中文版 - Obsidian中文论坛
- Obsidian插件篇-DataviewJS参考示例 - Obsidian中文论坛
- Development Guide - DeepWiki
- Change History - DeepWiki
本文链接: https://www.cnblogs.com/johnnyzen
关于博文:评论和私信会在第一时间回复,或直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
日常交流:大数据与软件开发-QQ交流群: 774386015 【入群二维码】参见左下角。您的支持、鼓励是博主技术写作的重要动力!

浙公网安备 33010602011771号