[!info] The Absolute Basics Add attributes to notes or tasks and query them, like a database or excel table
-
Your two basic entities are FILES and TASKS
-
You can use folders, files, tasks and links as SOURCES for your queries
\[\[note name]]
= links tooutgoing(\[\[note name]])
= links from
-
You can directly access links, tags and tasks!
- via
file.inlinks
,files.outlinks
,file.tags
,file.tasks
- via
-
You can use a bunch of pre-computed fields like
file.folder
andfile.mtime
-
You can use complex expressions & computed values
-
There's a very powerful Javascript API
You can add metadata to notes and tasks.
YAML at the top:
---
{field}: {value}
quality: 5
embed:
score: 2
---
On a single line:
{field}::value
Or inline: [{field}::value]
LIST - selects notes and lists them TABLE - selects notes and puts in a table CALENDAR - uses a date field to show a calendar
TASK - selects all - []
lines from notes that match the queries
- there is task-specific metadata (e.g. completed, section, subtasks)
FROM - tag, folder, file, link
- can combine these in REALLY COOL ways
- omitting searches everything
WHERE - a bunch of logic to filter your source (e.g. priority > 10
)
LIMIT number SORT desc/asc GROUP BY FLATTEN
NOTE: You can group and sort by expressions!
- rows - a reference to the rows included in a query or grouping
- e.g. after
grouping
the top level group array items will be available inrows
- e.g. after
- all field names that you add get treated as objects
- all lower case and spaces replaced with
-
(e.g. "some Attribute" will convert tosome-attribute
)
- all lower case and spaces replaced with
[[]]
references the current file in a regular query
Query things with dv.pages
, operate on them with javascript filters and such, then output via dv.el
or dv.table
You have access to certain JS things like new Date()
You have to sometimes convert an object with dv.page(o)
...e.g. file.inlinks.map()
From other scripts, you can access the dv
object with:
const dv = app.plugins.plugins.dataview.api
TABLE length(rows) as count
FLATTEN file.tags as tagz
GROUP BY tagz
SORT count DESC
TASK FROM #gap
LIMIT 5
GROUP BY file.folder
This is all the links TO notes that link mental models.
"2nd order links"
Take all the links to mental models and show me other links TO those files.
TABLE file.inlinks
FROM [[mental models]]
FLATTEN file.inlinks as links
GROUP BY links
This is all the links FROM notes that link mental models.
"Sibling links"
Take all the links to mental models and then show me other links in those files.
TABLE file.inlinks
FROM [[mental models]]
FLATTEN file.outlinks as links
GROUP BY links
LIST FROM #habit
You do dynamic queries and sum up properties like below:
- you can also use inlinks or outlinks and tags!
const habitPages = dv.pages("#habit")
let totalProgress = 0
habitPages.forEach(o => totalProgress += o.progress || 0)
dv.el("h5", "Habit Progress: " + totalProgress)
let page = "mental models";
let pages = new Set();
let stack = [page];
while (stack.length > 0) {
let elem = stack.pop();
let meta = dv.page(elem);
if (!meta) continue;
for (let inlink of meta.file.inlinks.concat(meta.file.outlinks).array()) {
console.log(inlink);
if (pages.has(inlink.path)) continue;
pages.add(inlink.path);
stack.push(inlink.path);
} } // Data is now the file metadata for every page that directly OR indirectly links to the current page. let data = dv.array(Array.from(pages)).map(p => dv.page(p));
const allFiles = dv.pages("")
const targetFolder = "test-tree"
const depthLimit = 1
const filesInTargetFolder = Array.from(allFiles).filter(o => o.file.folder.indexOf(targetFolder) >= 0)
const rootFolder = dv.app.vault.fileMap[targetFolder]
let fileStack = [[rootFolder, 0]]
const files = []
while(fileStack.length) {
const [file, depth] = fileStack.pop()
files.push(file)
if (file.children?.length && depth < depthLimit) {
console.log("concat children!")
fileStack = fileStack.concat(file.children.map(o => ([o, depth + 1])))
}
console.log("-----> recurse!", file, depth, fileStack)
}
console.log(files)
files.forEach(file => dv.el("p", file.name))
LIST
WHERE length(filter(synonyms, (word) => contains([[]].synonyms, word))) > 0 AND file.name != [[]].file.name
- filter out completed, future = true, stale = true, ignored >= 5
- if prompt = true, filter it out if
last-prompt
is more thanprompt-frequency
days ago - sort by priority, prompt and deadline
const IGNORED_MAX = 5
dv.taskList(dv.pages('"High Level!/TODO"').file.tasks.filter(o => !o.completed && !o.future && !o.stale && (!o.ignored || o.ignored < IGNORED_MAX) && (
!o.prompt || (
o.prompt && (
!o["last-prompt"] || (
dv.date(o["last-prompt"]) + dv.duration(
(o["prompt-frequency"] || "7") + " days"
) < dv.date(DateTime.now())
)
)
)
)).sort(o => o.priority, "desc").sort(o => o.prompt, "desc").sort(o => o.deadline, "desc"), false)