高级 Dataview 查询案例
本文将深入介绍 Dataview 的高级用法,通过实战案例帮助你掌握数据查询技巧。
基础回顾
Dataview 简介
Dataview 是一个强大的数据查询插件,可以将你的笔记变成数据库:
yaml
核心功能:
- 数据查询:从笔记中提取信息
- 数据展示:表格、列表、任务视图
- 数据操作:过滤、排序、分组
- 实时更新:自动同步数据变化基本语法
查询类型:
dataview
// 列表视图
LIST
FROM "folder"
// 表格视图
TABLE column1, column2
FROM "folder"
// 任务视图
TASK
FROM "folder"
// 日历视图
CALENDAR file.cday
FROM "folder"数据源:
dataview
// 按文件夹
FROM "Projects"
// 按标签
FROM #tag
// 按链接
FROM [[笔记名称]]
// 组合条件
FROM "Projects" OR #work
// 排除条件
FROM -"Templates"进阶查询案例
案例 1:项目进度追踪
场景:追踪多个项目的进度和状态
数据结构:
markdown
---
project: 项目名称
status: planning/active/completed/on-hold
priority: high/medium/low
start_date: 2024-01-01
due_date: 2024-06-30
progress: 60
---查询:活跃项目概览
dataview
TABLE
project as "项目名称",
status as "状态",
priority as "优先级",
progress as "进度",
due_date as "截止日期",
choice(
due_date < date(today),
"🔴 已逾期",
choice(
due_date < date(today) + dur(7 days),
"🟡 即将到期",
"🟢 进行中"
)
) as "状态标识"
FROM "01-Projects"
WHERE status = "active"
SORT priority ASC, due_date ASC查询:项目进度统计
dataview
TABLE WITHOUT ID
choice(
status = "active", "🟢 进行中",
choice(
status = "completed", "✅ 已完成",
choice(
status = "planning", "📋 规划中",
"⏸️ 暂停"
)
)
) as "状态",
length(rows) as "项目数",
default(round(sum(rows.progress) / length(rows), 1), 0) + "%" as "平均进度"
FROM "01-Projects"
GROUP BY status查询:本周到期项目
dataview
TABLE
project as "项目",
due_date as "截止日期",
progress as "当前进度",
due_date - date(today) as "剩余天数"
FROM "01-Projects"
WHERE status = "active" AND due_date <= date(today) + dur(7 days)
SORT due_date ASC案例 2:阅读管理
场景:管理书籍阅读进度和笔记
数据结构:
markdown
---
title: 书名
type: book
author: 作者
status: to-read/reading/done
rating: 0-5
start_date: 2024-01-01
finish_date: 2024-02-01
pages: 300
current_page: 150
tags: [book, fiction]
---查询:阅读进度看板
dataview
TABLE
title as "书名",
author as "作者",
status as "状态",
choice(
status = "done",
"✅ 已完成",
choice(
status = "reading",
round(current_page / pages * 100, 1) + "%",
"📚 待读"
)
) as "进度",
rating as "评分"
FROM #book
SORT choice(
status = "reading", 0,
choice(status = "to-read", 1, 2)
) ASC, rating DESC查询:本月阅读统计
dataview
TABLE WITHOUT ID
length(filter(rows, (r) => r.status = "done")) as "已完成",
length(filter(rows, (r) => r.status = "reading")) as "阅读中",
length(filter(rows, (r) => r.status = "to-read")) as "待读",
default(round(sum(filter(rows, (r) => r.status = "done").rating) / length(filter(rows, (r) => r.status = "done")), 2), 0) as "平均评分"
FROM #book
WHERE finish_date.month = date(today).month查询:高分书籍推荐
dataview
LIST
FROM #book
WHERE rating >= 4 AND status = "done"
SORT rating DESC
LIMIT 10查询:作者作品统计
dataview
TABLE WITHOUT ID
author as "作者",
length(rows) as "作品数",
round(sum(rows.rating) / length(rows), 2) as "平均评分",
join(limit(sort(map(rows, (r) => r.title), (a, b) => a < b), 3), ", ") as "代表作品"
FROM #book
WHERE status = "done"
GROUP BY author
SORT length(rows) DESC
LIMIT 10案例 3:任务管理
场景:管理个人任务和待办事项
数据结构:
markdown
---
created: 2024-01-01
due: 2024-01-15
completed: false
priority: high/medium/low
tags: [task, work]
---
# 任务标题
## 任务详情
- [ ] 子任务 1
- [x] 子任务 2
- [ ] 子任务 3查询:今日待办
dataview
TASK
FROM "Tasks" OR "01-Projects"
WHERE !completed AND due = date(today)
SORT priority ASC查询:本周任务概览
dataview
TABLE
file.link as "任务",
due as "截止日期",
priority as "优先级",
choice(
due < date(today),
"🔴 逾期",
choice(
due = date(today),
"🟡 今天",
"🟢 即将到期"
)
) as "状态"
FROM "Tasks"
WHERE !completed AND due >= date(today) - dur(1 day) AND due <= date(today) + dur(7 days)
SORT due ASC, priority ASC查询:任务完成率统计
dataview
TABLE WITHOUT ID
choice(
priority = "high", "🔴 高优先级",
choice(
priority = "medium", "🟡 中优先级",
"🟢 低优先级"
)
) as "优先级",
length(filter(rows, (r) => r.completed = true)) as "已完成",
length(filter(rows, (r) => r.completed = false)) as "未完成",
round(length(filter(rows, (r) => r.completed = true)) / length(rows) * 100, 1) + "%" as "完成率"
FROM "Tasks"
WHERE file.cday >= date(today) - dur(30 days)
GROUP BY priority查询:逾期任务提醒
dataview
TASK
FROM "Tasks"
WHERE !completed AND due < date(today)
SORT due ASC案例 4:笔记统计分析
场景:分析知识库的整体情况
查询:笔记增长趋势
dataview
TABLE WITHOUT ID
file.cday as "创建日期",
length(rows) as "新增笔记数"
FROM ""
WHERE file.cday >= date(today) - dur(30 days)
GROUP BY file.cday
SORT file.cday DESC查询:活跃度统计
dataview
TABLE WITHOUT ID
"本周" as "时间段",
length(filter(dv.pages(""), (p) => p.file.cday >= date(today) - dur(7 days))) as "新增笔记",
length(filter(dv.pages(""), (p) => p.file.mday >= date(today) - dur(7 days))) as "更新笔记",
length(filter(dv.pages(""), (p) => p.file.cday = date(today))) as "今日新增"
FROM ""
LIMIT 1查询:笔记类型分布
dataview
TABLE WITHOUT ID
choice(
type = "project", "📁 项目",
choice(
type = "book", "📚 书籍",
choice(
type = "article", "📝 文章",
choice(
type = "note", "📋 笔记",
"📄 其他"
)
)
)
) as "类型",
length(rows) as "数量",
round(length(rows) / length(dv.pages("")) * 100, 1) + "%" as "占比"
FROM ""
WHERE type
GROUP BY type
SORT length(rows) DESC查询:标签使用统计
dataview
TABLE WITHOUT ID
file.tags as "标签",
length(rows) as "使用次数"
FROM ""
WHERE length(file.tags) > 0
GROUP BY file.tags
SORT length(rows) DESC
LIMIT 20查询:孤立笔记检测
dataview
TABLE
file.link as "笔记",
length(file.inlinks) as "被引用次数",
length(file.outlinks) as "引用次数"
FROM ""
WHERE length(file.inlinks) = 0 AND length(file.outlinks) = 0
SORT file.ctime DESC
LIMIT 20案例 5:学习进度管理
场景:追踪学习课程和知识点
数据结构:
markdown
---
course: 课程名称
topic: 主题
status: not-started/learning/completed
difficulty: beginner/intermediate/advanced
hours: 5
progress: 80
tags: [learning, course]
---
# 知识点标题
## 学习笔记
## 练习题查询:学习进度看板
dataview
TABLE
course as "课程",
topic as "主题",
status as "状态",
progress as "进度",
hours as "学时"
FROM "Learning"
WHERE status != "completed"
SORT course ASC, progress DESC查询:课程完成统计
dataview
TABLE WITHOUT ID
course as "课程",
length(rows) as "知识点总数",
length(filter(rows, (r) => r.status = "completed")) as "已完成",
round(
length(filter(rows, (r) => r.status = "completed")) / length(rows) * 100, 1
) + "%" as "完成率",
sum(rows.hours) as "总学时"
FROM "Learning"
GROUP BY course
SORT length(rows) DESC查询:难度分布
dataview
TABLE WITHOUT ID
choice(
difficulty = "beginner", "🔰 入门",
choice(
difficulty = "intermediate", "⭐ 进阶",
"🚀 高级"
)
) as "难度",
length(rows) as "知识点数",
length(filter(rows, (r) => r.status = "completed")) as "已完成"
FROM "Learning"
GROUP BY difficulty查询:学习时间统计
dataview
TABLE WITHOUT ID
sum(rows.hours) as "总学时",
default(sum(filter(rows, (r) => r.status = "completed").hours), 0) as "已学完",
default(sum(filter(rows, (r) => r.status = "learning").hours), 0) as "学习中",
default(sum(filter(rows, (r) => r.status = "not-started").hours), 0) as "未开始"
FROM "Learning"案例 6:会议记录管理
场景:管理会议记录和待办事项
数据结构:
markdown
---
date: 2024-01-15
type: meeting
project: 项目名称
attendees: [张三, 李四]
---
# 会议记录
## 会议主题
## 待办事项
- [ ] 任务 1 - @张三
- [ ] 任务 2 - @李四查询:近期会议记录
dataview
TABLE
date as "日期",
project as "项目",
join(attendees, ", ") as "参会人员"
FROM "Meetings"
WHERE date >= date(today) - dur(30 days)
SORT date DESC
LIMIT 10查询:项目会议统计
dataview
TABLE WITHOUT ID
project as "项目",
length(rows) as "会议次数",
join(limit(sort(map(rows, (r) => r.date), (a, b) => a > b), 3), ", ") as "最近会议"
FROM "Meetings"
GROUP BY project
SORT length(rows) DESC查询:会议待办追踪
dataview
TASK
FROM "Meetings"
WHERE !completed
SORT file.link ASC案例 7:健康习惯追踪
场景:追踪每日健康习惯
数据结构:
markdown
---
date: 2024-01-01
type: daily-habits
sleep: 7
exercise: true
meditation: true
reading: true
water: 8
mood: good
---
# 习惯记录
## 今日习惯
- [x] 晨起运动
- [x] 阅读 30 分钟
- [x] 冥想 10 分钟查询:本周习惯完成率
dataview
TABLE WITHOUT ID
"晨起运动" as "习惯",
round(sum(filter(rows, (r) => r.exercise = true)) / length(rows) * 100, 1) + "%" as "完成率"
FROM "Habits"
WHERE date >= date(today) - dur(7 days)
GROUP BY true
UNION
TABLE WITHOUT ID
"冥想" as "习惯",
round(sum(filter(rows, (r) => r.meditation = true)) / length(rows) * 100, 1) + "%" as "完成率"
FROM "Habits"
WHERE date >= date(today) - dur(7 days)
GROUP BY true
UNION
TABLE WITHOUT ID
"阅读" as "习惯",
round(sum(filter(rows, (r) => r.reading = true)) / length(rows) * 100, 1) + "%" as "完成率"
FROM "Habits"
WHERE date >= date(today) - dur(7 days)
GROUP BY true查询:睡眠质量统计
dataview
TABLE WITHOUT ID
avg(rows.sleep) as "平均睡眠时长",
max(rows.sleep) as "最长睡眠",
min(rows.sleep) as "最短睡眠"
FROM "Habits"
WHERE date >= date(today) - dur(30 days)查询:心情分布
dataview
TABLE WITHOUT ID
choice(
mood = "good", "😊 很好",
choice(
mood = "normal", "😐 一般",
"😔 不好"
)
) as "心情",
length(rows) as "天数",
round(length(rows) / sum(map(filter(dv.pages("Habits"), (p) => p.date >= date(today) - dur(30 days)), (r) => 1)) * 100, 1) + "%" as "占比"
FROM "Habits"
WHERE date >= date(today) - dur(30 days)
GROUP BY mood
SORT length(rows) DESC案例 8:内容创作管理
场景:管理博客文章创作流程
数据结构:
markdown
---
title: 文章标题
status: idea/draft/review/published
category: 分类
published_date:
word_count: 0
views: 0
tags: [blog, topic]
---
# 文章标题
## 大纲
## 内容
## 发布检查
- [ ] 标题优化
- [ ] SEO 检查
- [ ] 图片优化查询:文章创作看板
dataview
TABLE
title as "标题",
status as "状态",
word_count as "字数",
choice(
status = "published",
"✅ 已发布",
choice(
status = "review",
"📝 审核中",
choice(
status = "draft",
"✏️ 草稿",
"💡 想法"
)
)
) as "状态标识"
FROM "Blog"
SORT choice(
status = "idea", 0,
choice(status = "draft", 1,
choice(status = "review", 2, 3))
) ASC, word_count DESC查询:本月发布统计
dataview
TABLE WITHOUT ID
length(filter(rows, (r) => r.status = "published")) as "已发布",
length(filter(rows, (r) => r.status = "review")) as "审核中",
length(filter(rows, (r) => r.status = "draft")) as "草稿",
sum(filter(rows, (r) => r.status = "published").word_count) as "总字数"
FROM "Blog"
WHERE published_date.month = date(today).month查询:热门文章排行
dataview
TABLE
title as "文章",
views as "浏览量",
word_count as "字数",
published_date as "发布日期"
FROM "Blog"
WHERE status = "published"
SORT views DESC
LIMIT 10查询:分类统计
dataview
TABLE WITHOUT ID
category as "分类",
length(rows) as "文章数",
sum(rows.word_count) as "总字数",
sum(rows.views) as "总浏览"
FROM "Blog"
WHERE status = "published"
GROUP BY category
SORT sum(rows.views) DESC高级技巧
技巧 1:内联查询
在文本中直接插入查询:
markdown
我今天有 `= length(filter(dv.pages("Tasks"), (t) => !t.completed AND t.due = date(today)))` 个待办任务。
本周新增笔记:`= length(filter(dv.pages(""), (p) => p.file.cday >= date(today) - dur(7 days)))` 篇。
当前项目进度:`= default(dv.page("Projects/当前项目").progress, 0) %`。技巧 2:条件渲染
根据条件显示不同内容:
dataview
TABLE
title as "标题",
choice(
progress >= 80, "🚀 接近完成",
choice(
progress >= 50, "💪 进展顺利",
choice(
progress >= 20, "🐌 刚刚开始",
"💤 尚未开始"
)
)
) as "进度状态"
FROM "Projects"技巧 3:数据计算
复杂的数据计算:
dataview
TABLE WITHOUT ID
project as "项目",
start_date as "开始日期",
due_date as "截止日期",
due_date - date(today) as "剩余天数",
round((due_date - start_date).days, 0) as "总天数",
round(progress * (due_date - start_date).days / 100, 0) as "已用天数",
choice(
(due_date - start_date).days - round(progress * (due_date - start_date).days / 100, 0) < 0,
"⚠️ 可能延期",
"✅ 进度正常"
) as "风险提示"
FROM "Projects"
WHERE status = "active"技巧 4:多表联合
使用 UNION 合并多个查询:
dataview
TABLE WITHOUT ID
"项目笔记" as "类型", length(rows) as "数量"
FROM "Projects"
GROUP BY true
UNION
TABLE WITHOUT ID
"学习笔记" as "类型", length(rows) as "数量"
FROM "Learning"
GROUP BY true
UNION
TABLE WITHOUT ID
"会议记录" as "类型", length(rows) as "数量"
FROM "Meetings"
GROUP BY true技巧 5:自定义函数
在 DataviewJS 中使用自定义函数:
dataviewjs
// 自定义统计函数
function getStats(pages) {
let total = pages.length;
let completed = pages.where(p => p.status === "completed").length;
let percent = total > 0 ? Math.round(completed / total * 100) : 0;
return { total, completed, percent };
}
// 查询项目统计
let projects = dv.pages("01-Projects");
let stats = getStats(projects);
dv.paragraph(`
📊 **项目统计**
- 总项目数:${stats.total}
- 已完成:${stats.completed}
- 完成率:${stats.percent}%
`);技巧 6:动态仪表板
创建自动更新的仪表板:
dataviewjs
// 获取数据
let pages = dv.pages("");
let today = dv.date("today");
// 计算统计数据
let stats = {
total: pages.length,
todayNew: pages.where(p => p.file.cday.equals(today)).length,
weekNew: pages.where(p => p.file.cday >= today.minus({days: 7})).length,
monthNew: pages.where(p => p.file.cday >= today.minus({days: 30})).length
};
// 显示统计卡片
dv.paragraph(`
# 📊 知识库统计
<div style="display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px;">
<div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 20px; border-radius: 10px; color: white; text-align: center;">
<div style="font-size: 32px; font-weight: bold;">${stats.total}</div>
<div>总笔记数</div>
</div>
<div style="background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%); padding: 20px; border-radius: 10px; color: white; text-align: center;">
<div style="font-size: 32px; font-weight: bold;">${stats.todayNew}</div>
<div>今日新增</div>
</div>
<div style="background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%); padding: 20px; border-radius: 10px; color: white; text-align: center;">
<div style="font-size: 32px; font-weight: bold;">${stats.weekNew}</div>
<div>本周新增</div>
</div>
<div style="background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%); padding: 20px; border-radius: 10px; color: white; text-align: center;">
<div style="font-size: 32px; font-weight: bold;">${stats.monthNew}</div>
<div>本月新增</div>
</div>
</div>
`);性能优化
优化建议
1. 限制查询范围:
dataview
// ❌ 不推荐:查询所有笔记
FROM ""
// ✅ 推荐:限定文件夹
FROM "Projects"
// ✅ 推荐:限定标签
FROM #project2. 使用索引字段:
dataview
// ✅ 使用 frontmatter 字段
WHERE status = "active"
// ✅ 使用文件属性
WHERE file.cday >= date(today) - dur(7 days)3. 避免复杂计算:
dataview
// ❌ 不推荐:复杂嵌套
TABLE (
length(filter(...))
) as "计算"
// ✅ 推荐:简化查询
TABLE status, progress
WHERE status = "active"4. 分页查询:
dataview
// 使用 LIMIT 限制结果数量
TABLE title, date
FROM "Blog"
SORT date DESC
LIMIT 105. 缓存查询结果:
dataviewjs
// 使用变量缓存查询结果
let allPages = dv.pages("");
// 多次使用同一查询
let projects = allPages.where(p => p.type === "project");
let tasks = allPages.where(p => p.type === "task");常见问题
Q1: 查询不显示结果?
yaml
检查清单:
1. 数据源是否存在
- 文件夹名称是否正确
- 标签是否存在
2. Frontmatter 格式是否正确
- YAML 语法是否正确
- 字段名是否拼写正确
3. 查询条件是否匹配
- 条件是否过于严格
- 是否有数据满足条件
4. 插件是否启用
- Dataview 是否已安装启用
- 是否有语法错误Q2: 如何调试查询?
dataviewjs
// 调试方法:输出原始数据
let pages = dv.pages("Projects");
console.log(pages); // 在控制台查看
// 检查字段
dv.paragraph(`
字段列表:${pages.keys().join(", ")}
笔记数量:${pages.length}
第一条:${pages.first().file.link}
`);Q3: 查询速度慢怎么办?
yaml
优化方法:
1. 减少查询范围
- 使用 FROM 限定
- 添加 WHERE 条件
2. 简化查询
- 减少计算字段
- 避免嵌套查询
3. 使用索引
- 在 frontmatter 中定义字段
- 使用内置属性
4. 异步加载
- 分批查询
- 延迟加载参考资源
下一步
- Templater 高级教程 - 自动化模板
- QuickAdd 插件 - 快速添加内容
- 从0到1建立知识库 - 完整构建流程