Skip to content

Instantly share code, notes, and snippets.

@Goondrious
Last active October 23, 2022 15:10
Show Gist options
  • Save Goondrious/e91bfd8b221ffac052cc9f1aa7f21e26 to your computer and use it in GitHub Desktop.
Save Goondrious/e91bfd8b221ffac052cc9f1aa7f21e26 to your computer and use it in GitHub Desktop.

[!info] The Absolute Basics Add attributes to notes or tasks and query them, like a database or excel table

Official Reference

High Level

  • Your two basic entities are FILES and TASKS

  • You can use folders, files, tasks and links as SOURCES for your queries

    • \[\[note name]] = links to
    • outgoing(\[\[note name]]) = links from
  • You can directly access links, tags and tasks!

    • via file.inlinks, files.outlinks,file.tags, file.tasks
  • You can use a bunch of pre-computed fields like file.folder and file.mtime

  • You can use complex expressions & computed values

  • There's a very powerful Javascript API

Annotations

Reference

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]

Query Syntax

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!

Special Objects

  • 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 in rows
  • all field names that you add get treated as objects
    • all lower case and spaces replaced with - (e.g. "some Attribute" will convert to some-attribute)
  • [[]] references the current file in a regular query

Javascript API

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

Snippets

Tags - Group and Flatten

TABLE length(rows) as count
FLATTEN file.tags as tagz
GROUP BY tagz
SORT count DESC

Task - show list of tasks, grouped by file folder

TASK FROM #gap 
LIMIT 5
GROUP BY file.folder

Links from links from a note

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

Links to links from a note

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

Sum attributes

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)

Recursively get all links to a file:

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));

Recursively get file tree from Obsidian app api

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))

Get all files that have any match in a list attribute

LIST
WHERE length(filter(synonyms, (word) => contains([[]].synonyms, word))) > 0 AND file.name != [[]].file.name

A Task List

  • filter out completed, future = true, stale = true, ignored >= 5
  • if prompt = true, filter it out if last-prompt is more than prompt-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)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment