查询展示笔记元数据
table this
where file = this.file
示例
- 创建时间最近三天的笔记
table file.ctime as "创建日期"
where date(today) - file.ctime <= dur(3 day)
sort file.ctime desc文档元数据操作
有两种方式添加元数据:
- 文档属性
- 内联字段
文档属性
添加文档属性,以key:value的形式。
身高 177cm内联字段
以键值对形式存在
1. 单独成行
身高::177cm
2. 行内字段插入某一行
示例:[体重::52kg]
示例:(年龄::22)// ==== 1. 收集任务 ====
let tasks1 = dv.pages('"插件学习"').file.tasks;
let tasks = [...tasks1]
//...tasks2, ...tasks3, ...tasks4, ...tasks5];
// 查询路径条件
let basePaths = `(path includes CYG-Works)`;
let today = dv.date("today");
let tomorrow = dv.date("tomorrow");
let oneWeekLater = today.plus({ days: 6 });
console.log(tasks)// 获取所有任务文件夹中的文件
const pages = dv.pages('"Tasks"');
// 创建一个对象来存储标签分类
const tagMap = {};
// 遍历每个文件
pages.forEach(page => {
if (page.file.tags) {
page.file.tags.forEach(tag => {
// 如果标签不存在于tagMap中,初始化为一个空数组
if (!tagMap[tag]) {
tagMap[tag] = [];
}
// 将文件名添加到对应标签的数组中
tagMap[tag].push(page.file.name);
});
}
});
// 输出结果
// 遍历每个标签并创建一个表格
Object.entries(tagMap).forEach(([tag, tasks]) => {
dv.header(3, `Tag: ${tag}`); // 显示标签作为标题
dv.table(["Task Name"], tasks.map(task => [task])); // 显示任务列表
});
// ==== 1. 收集任务 ====
let tasks1 = dv.pages('"插件学习"').file.tasks;
let tasks = [...tasks1]
//...tasks2, ...tasks3, ...tasks4, ...tasks5];
// 查询路径条件
let basePaths = `(path includes 插件学习)`;
let today = dv.date("today");
let tomorrow = dv.date("tomorrow");
let oneWeekLater = today.plus({ days: 6 });
// ==== 2. 分类任务 ====
let expiredTasks = tasks.filter(t => t.status === " " && (
(t.due && dv.date(t.due).toJSDate() < today.toJSDate()) ||
(t.scheduled && dv.date(t.scheduled).toJSDate() < today.toJSDate())
));
let ongoingTasks = tasks.filter(t => t.status === "/");
let todoTasks = tasks.filter(t => t.status === " ");
console.log(tasks[0])// 获取所有任务文件夹中的文件
const pages = dv.pages('"CYG-Works/IT工单"');
// 创建一个对象来存储标签分类
const tagMap = {};
// 遍历每个文件
pages.forEach(page => {
// 确保文件中有标签
if (page.file.tags) {
// 遍历每个标签
page.file.tags.forEach(tag => {
// 如果标签不存在于tagMap中,初始化为0
if (!tagMap.hasOwnProperty(tag)) {
tagMap[tag] = 0;
}
// 增加该标签的计数
tagMap[tag] += 1;
});
}
});
// 输出结果
// 创建一个表格显示标签及其对应的文件数量
dv.table(["Tag", "Count"],
Object.entries(tagMap).map(([tag, count]) => [tag, count])
);
table file.name as "Task Name", file.tags as "Tags"
from "CYG-Works"
flatten file.tags as tag sort tag
笔记库查询代码汇总
模板库 js
- 用于 日常笔记模板 >> 今日任务动态
// ============================================
// 今日任务动态查询
// 功能:根据当前日记的 journal-date 日期,查找相关任务笔记
// ============================================
// --- 第1步:获取当前日记的日期 ---
// dv.current() 获取当前正在查看的笔记(即这篇日记)
// ["journal-date"] 读取日记 frontmatter 中的 journal-date 字段
const raw = dv.current()["journal-date"];
// 将日期统一转为 "yyyy-MM-dd" 字符串格式
// 如果 raw 是 Dataview 日期对象(有 toFormat 方法),就格式化
// 否则直接转字符串(兼容文本格式的日期)
const dateStr = typeof raw?.toFormat === "function"
? raw.toFormat("yyyy-MM-dd")
: String(raw);
// 将字符串转为 Dataview 日期对象,用于范围比较
const start = dv.date(dateStr);
// 计算次日,用于创建日期的区间查询 [当天, 次日)
const end = start.plus({ days: 1 });
// ============================================
// 辅助函数:递归渲染任务树(含子任务缩进)
// ============================================
function renderTasks(tasks, depth = 0) {
let lines = [];
for (const t of tasks) {
// 根据层级生成缩进(depth=0 不缩进,depth=1 一个Tab,以此类推)
const indent = "\t".repeat(depth);
// 根据完成状态显示不同复选框
// t.completed 为 true 表示已完成([x]),false 表示未完成([ ])
const checkbox = t.completed ? "- [x] " : "- [ ] ";
// 拼接缩进 + 复选框 + 任务文本
lines.push(indent + checkbox + t.text);
// 递归处理子任务(如果存在)
// ?. 是可选链,避免 subtasks 不存在时报错
if (t.subtasks?.length > 0) {
lines = lines.concat(renderTasks(t.subtasks, depth + 1));
}
}
return lines;
}
// ============================================
// 辅助函数:过滤出顶层任务(排除重复子任务)
// ============================================
// Dataview 的 p.file.tasks 会扁平化返回所有任务
// 子任务既会出现在父任务的 subtasks 中,也会作为独立项出现
// 这个函数去重,只保留根级任务
function getRootTasks(allTasks) {
const subLines = new Set();
// 收集所有子任务的行号
for (const t of allTasks) {
if (t.subtasks) {
for (const s of t.subtasks) {
subLines.add(s.line);
}
}
}
// 过滤:只保留不在 subLines 中的任务(即不是任何任务的子任务)
return allTasks.filter(t => !subLines.has(t.line));
}
// ============================================
// 主查询:构建表格
// ============================================
dv.table(
// 表头
["任务", "待办项"],
// 从指定文件夹查询所有笔记
dv.pages('"CYG-Works/需求任务-Tasks"')
// --- 筛选条件(满足任一即可)---
.where(p => {
// 条件1:笔记创建日期等于 journal-date 当天
// cday = creation day(创建日期)
// 用 >= start 且 < end 实现"等于当天"(避免时区问题)
if (p.file.cday >= start && p.file.cday < end) return true;
// 条件2:笔记中任意任务项的文本包含该日期
// tasks 只匹配任务列表(- [ ] / - [x]),不匹配普通列表
// 适用于任务中标注了截止日期(🗓️)或创建日期(➕)的场景
return p.file.tasks.some(t => t.text.includes(dateStr));
})
// --- 排序:按修改日期倒序(最新的在前)---
// mday = modification day(修改日期)
.sort(p => p.file.mday, "desc")
// --- 映射输出 ---
.map(p => [
// 第1列:笔记链接(可点击跳转)
p.file.link,
// 第2列:该笔记中的所有任务(层级渲染)
// 1. getRootTasks 去重,只保留顶层任务
// 2. renderTasks 递归渲染,带子任务缩进
// 3. join("\n") 用换行拼接,表格内显示为多行
renderTasks(getRootTasks(p.file.tasks)).join("\n")
])
);- 用于 日常笔记模板 >> 工作日志
// ============================================
// 时间队列查询
// 功能:从任务笔记的"时间队列"中,查找与 journal-date 日期相关的记录
// ============================================
// --- 第1步:获取当前日记的日期 ---
// dv.current() 获取当前正在查看的笔记(即这篇日记)
// ["journal-date"] 读取日记 frontmatter 中的 journal-date 字段
const raw = dv.current()["journal-date"];
// 将日期统一转为 "yyyy-MM-dd" 字符串格式
// 如果 raw 是 Dataview 日期对象(有 toFormat 方法),就格式化
// 否则直接转字符串(兼容文本格式的日期)
const dateStr = typeof raw?.toFormat === "function"
? raw.toFormat("yyyy-MM-dd")
: String(raw);
// ============================================
// 辅助函数:递归收集子列表内容
// ============================================
// 参数 item:当前列表项(Dataview 的 list item 对象)
// 参数 depth:当前层级(0=直接子项,1=孙项,以此类推)
function collectChildren(item, depth = 0) {
let lines = [];
// item.children 包含该列表项的所有子项
// 注意:如果 item 没有子项,item.children 可能为 undefined,用 || [] 兜底
for (const child of (item.children || [])) {
// 根据层级生成缩进:层级越深,缩进越多
// depth=0 时缩进1个空格,depth>0 时用 Tab 缩进
const prefix = depth > 0 ? "\t".repeat(depth) : " ";
// 使用子项自身的符号(如 - [ ]),如果没有则 fallback 到父项符号或 "-"
const symbol = child.symbol || item.symbol || "-";
// 拼接缩进 + 符号 + 子项文本
lines.push(prefix + symbol + " " + child.text);
// 递归收集孙项、曾孙项...
lines = lines.concat(collectChildren(child, depth + 1));
}
return lines;
}
// ============================================
// 主查询:构建表格数据
// ============================================
// 存储表格行数据
const rows = [];
// 从指定文件夹查询所有笔记,按文件名降序排列
// 降序排列让最新的笔记排在前面(假设文件名包含日期或序号)
const pages = dv.pages('"CYG-Works/需求任务-Tasks"').sort(p => p.file.name, "desc");
// 遍历每个笔记
for (const page of pages) {
// --- 筛选:找出包含目标日期的顶层普通列表项 ---
// page.file.lists 获取笔记中所有列表项(普通列表 + 任务列表)
//
// 匹配条件(三个条件同时满足):
// 1. !item.task:排除任务列表(只保留普通列表项,如 "- 2026-05-09 11:19")
// 2. item.text.includes(dateStr):文本中包含当前日记日期
// 3. item.parent === undefined:只匹配顶层列表项
// 避免子内容里的日期被误匹配(如备注中提到其他日期)
const entries = page.file.lists.where(item =>
!item.task &&
item.text.includes(dateStr) &&
item.parent === undefined
);
// --- 处理匹配到的每个时间记录 ---
// first 标记:同一笔记的多个时间记录,只在第一行显示笔记链接
// 这样表格更简洁,避免链接重复
let first = true;
for (const entry of entries) {
// entry.text 是时间记录本身的文本(如 "- 2026-05-09 11:19")
// .trim() 去掉首尾空格
const time = entry.text.trim();
// 递归收集该时间记录下的所有子项内容
// 用 join("\n") 把多行内容拼接成一个字符串,便于在表格单元格内显示
const content = collectChildren(entry).join("\n");
// 添加到表格行
rows.push([
// 第1列:笔记链接(同一笔记只显示一次,后续为空字符串)
first ? page.file.link : "",
// 第2列:时间记录文本(如 "- 2026-05-09 11:19")
time,
// 第3列:子项内容(多行,用换行拼接)
// 如果 content 为空,显示 "—" 作为占位符
content || "—"
]);
// 后续同一笔记的记录不再显示链接
first = false;
}
}
// ============================================
// 渲染表格
// ============================================
dv.table(
// 表头
["任务", "时间", "内容"],
// 表格数据
rows
);