关于DataView
DataView 是一个强大的插件,它允许你使用 SQL 语法查询和分析你的笔记。它可以帮助你:
- 任务与项目管理
- 个人知识管理(PKM)
- 财务与健康跟踪
- ……
项目地址:dataview github
基础知识
DataView包含两大逻辑模块:Indexer和Query Engine。
- Indexer负责索引你的笔记,将笔记的元数据和内容存储到数据库中。
- Query Engine负责执行查询,从数据库中获取数据。
DataView的查询语法基于 SQL,你可以使用 SQL 的语法来查询数据。
制作索引:frontmatter中的数据或者笔记中的key::value
数据。
查询方式:DQL(DataView Query Language)或者DJS(DataView JavaScript)。
更多知识可以参考:dataview参考手册
使用DataView Query(以0.5.63为例)
DQL模式:
1 2 3 4 5
| <QUERY-TYPE> <fields> FROM <source> <DATA-COMMAND> <expression> <DATA-COMMAND> <expression> ...
|
其中QUERY-TYPE是必须的,可以是LIST, TABLE, TASK 和 CALENDAR。
其他都是非必须的。
FROM:后面跟标签、目录、文件或者链接。必须放在DATA-COMMAND前面,而且最多只能使用一次。
DATA-COMMAND可以无限添加。下面介绍一些具体案例。
使用DataView JS
dataview中执行JS代码,拥有和插件代码一样的权限。
案例一:生成卡片样式的图册
效果:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| async function getRefCounts() { const allLinks = []; for (const page of dv.pages().file) { const content = await dv.io.load(page.path); const links = content.match(/!\[\[(.*?)(?:\|.*?)?\]\]/g) || []; allLinks.push(...links.map(link => link.replace(/!\[\[(.*?)(?:\|.*?)?\]\]/, "$1"))); } const refCounts = {}; allLinks.forEach(link => { const normalizedLink = link.startsWith("/") ? link.slice(1) : link; refCounts[normalizedLink] = (refCounts[normalizedLink] || 0) + 1; });
return refCounts; }
async function imageCardView() { const imageFiles = app.vault.getFiles() .filter(f => [".png", ".jpg", ".jpeg", ".gif", ".webp", ".svg"] .some(ext => f.path.toLowerCase().endsWith(ext)));
const refCounts = await getRefCounts(); let html = `<div style="display: flex; flex-wrap: wrap; gap: 16px;">`; imageFiles.sort((a, b) => { const aCount = refCounts[a.name] || 0; const bCount = refCounts[b.name] || 0; return bCount - aCount; }); for (const file of imageFiles) { const imgSrc = app.vault.adapter.getResourcePath(file.path); const fileName = file.name; const fileSize = (file.stat.size / 1024).toFixed(1) + ' KB'; const mtime = new Date(file.stat.mtime).toLocaleDateString(); let count = 0; Object.keys(refCounts).forEach(link => { if (link === fileName) { count += refCounts[link]; } });
html += ` <div onclick="app.workspace.openLinkText('${file.path}', '', false)" style="cursor:pointer;width:180px;"> <a href="${imgSrc}" target="_blank" style="text-decoration: none; color: inherit;"> <div style="width: 180px; border: 1px solid #eee; border-radius: 8px; box-shadow: 2px 2px 8px #eee; padding: 8px; text-align: center; background: var(--background-primary);"> <img src="${imgSrc}" alt="${fileName}" style="max-width: 160px; max-height: 120px; border-radius: 4px; margin-bottom: 8px;" /> <div style="font-size: 13px; margin-bottom: 4px;">${fileName}</div> <div style="font-size: 12px; color: #888;">${fileSize}</div> <div style="font-size: 12px; color: #aaa;">${mtime}</div> <div style="font-size: 12px; color: #d2691e; margin-top: 4px;">引用次数:${count}</div> </div> </a> </div>`; } html += `</div>`; dv.container.innerHTML = html; }
imageCardView();
|
案例二:获取插件列表
效果:

1 2 3 4 5 6 7 8 9 10 11 12 13
| const plugins = Object.keys(app.plugins.manifests) .map(id => { const m = app.plugins.manifests[id]; return [ m.name, m.version, m.author, m.description, app.plugins.enabledPlugins.has(id) ]; });
dv.table(["Name", "Version", "Author", "Description", "Loaded"], plugins);
|