Treat your obsidian vault as a database which you can query from. Provides a fully-fledged query language for filtering, sorting, and extracting data from your pages. See the Examples section below for some quick examples, or the full reference.
For plugin developer who want to utilize dataview api, check here to get type definitions and method to get api on load.
Show all games in the game folder, sorted by rating, with some metadata:
```dataview
table time-played, length, rating
from "games"
sort rating desc
```
List games which are MOBAs or CRPGs.
```dataview
list from #game/moba or #game/crpg
```
List all tasks in un-completed projects:
```dataview
task from #projects/active
```
List all of the files in the books
folder, sorted by the last time you modifed the file:
```dataview
table mtime from "books"
sort mtime desc
```
List all files which have a date in their title (of the form yyyy-mm-dd
), and list them by date order.
```dataview
list where file.day
sort file.day desc
```
Note: See the full documentation here.
Dataview allows you to write queries over markdown files which can be filtered by folder, tag, and markdown YAML fields; it can then display the resulting data in various formats. All dataviews are embedded code blocks with the general form:
```dataview
[list|table|task] field1, (field2 + field3) as myfield, ..., fieldN
from #tag or "folder" or [[link]] or outgoing([[link]])
where field [>|>=|<|<=|=|&|'|'] [field2|literal value] (and field2 ...) (or field3...)
sort field [ascending|descending|asc|desc] (ascending is implied if not provided)
```
The first word in a query is always the view type - currently, either:
list
, which just renders a list of files that pass the query filters.table
, which renders files and any selected fields that pass the query filters.task
, which renders all tasks from any files that pass the query filters.
You can query from either #tags
, from "folder"
, or from [[link]]
. You can freely combine these filters into more complicated boolean expressions using and
and or
; if precedence is important, use parentheses.
Fields can be any YAML front-matter field (currently, strings, numbers, ISO dates and durations are supported, with support for ratings, links, and intervals forthcoming), any custom defined field (using the field as field2
syntax). You can obtain fields inside of YAML objects using the .
operator - i.e., Dates.Birthday
for example. Fields can also be functions of other fields - for example, rating + offset
, is a valid field.
All files have the following implicit attributes:
file.name
: The file title.file.path
: The full file path.file.size
: The size (in bytes) of the file.file.ctime
: The date that the file was created.file.mtime
: The date that the file was last modified.
If the file has a date inside its title (of form yyyy-mm-dd
), it also obtains the following attributes:
file.day
: The date contained in the file title.
Additionally, all of the fields defined in the YAML front-matter are available for querying. You can query inside nested objects using dot notation (so dates.birthday
would get the birthday
object inside the dates
field). Fields can have the following types:
number
: A number like0
or18
or19.37
.date
: A date and time in ISO8601 format -yyyy-mm-ddThh:mm:ss
. Everything after the year and month is optional, so you can just writeyyyy-mm
oryyyy-mm-dd
oryyyy-mm-ddThh
. If you want to use a date in a query, usedate(<date>)
where<date>
is either a date,today
,tomorrow
,eom
(end of month), oreoy
(end of year).- You can access date fields like 'years' and so on via dot-notation (i.e.,
date(today).year
).
- You can access date fields like 'years' and so on via dot-notation (i.e.,
duration
: A length of time - can be added/subtracted from dates. Has the format<number> years/months/.../seconds
, where the unit can be years, months, weeks, days, hours, minutes, or seconds. If you want to use a duration in a query, usedur(<duration>)
.- You can access duration fields like 'years' and so on via dot-notation (i.e.,
dur(<duration>).years
).
- You can access duration fields like 'years' and so on via dot-notation (i.e.,
link
: An obsidian link (in the same format); you can use dot-notation to get fields in the linked file. For example,[[2020-09-20]].file.ctime
would get the creation time of the2020-09-20
note.array
: A list of elements. Automatically created by YAML lists in the frontmatter; can manually be created usinglist(elem1, elem2, ...)
.object
: A mapping of name -> value. Automatically created from YAML objects. You can access elements inside an object using dot-notation or array notation (object.field
orobject["field"]
).string
: Generic fallback; if a field is not a more specific type, it is a string, which is just text. To use a string in a query, use quotes - so"string"
.
- run
npm i -D obsidian-dataview
in your plugin dir - create a new file named
types.d.ts
under the same dir asmain.ts
- copy the following code into new file, then you can
- check if dataview enabled:
plugin.app.enabledPlugins.has("dataview")
- access dataview api:
plugin.app.plugins.dataview?.api
(may return undefined) - bind to dataview events:
plugin.registerEvent(plugin.app.metadataCache.on("dataview:...",(...)=>{...}))
- check if dataview enabled:
import "obsidian";
import { DataviewApi } from "obsidian-dataview";
declare module "obsidian" {
interface App {
plugins: {
enabledPlugins: Set<string>;
plugins: {
[id: string]: any;
dataview?: {
api?: DataviewApi;
};
};
}
interface MetadataCache {
on(
name: "dataview:api-ready",
callback: (api: DataviewPlugin["api"]) => any,
ctx?: any
): EventRef;
on(
name: "dataview:metadata-change",
callback: (
...args:
| [op: "rename", file: TAbstractFile, oldPath: string]
| [op: "delete", file: TFile]
| [op: "update", file: TFile]
) => any,
ctx?: any
): EventRef;
}
}
PS: method to check if api is available when loading plugin:
async onload() {
const doSomethingWith = (api: DataviewPlugin["api"]) => {
// do something
};
if (this.app.enabledPlugins.has("dataview")) {
const api = this.app.plugins.dataview?.api;
if (api) doSomethingWith(api);
else
this.registerEvent(
this.app.metadataCache.on("dataview:api-ready", (api) =>
doSomethingWith(api)
)
);
}
}
Value utils is exposed to check types of data:
import { Values } from "obsidian-dataview"
const field = plugin.app.plugins.dataview?.api.page('sample.md').field;
if (!field) return;
if (Values.isHtml(field)) // do something
else if (Values.isLink(field)) // do something
// ...
There is a lot of potential for a generic query system; here is the upcoming features (roughly sorted in order in which I'll work on them):
- Query/frontmatter date and duration support
- Expose folder creation time and last modified time as date fields
file.ctime
andfile.mtime
. - Expose daily note days as date field
file.day
. - Add shorthands for some date constants -
today
,tommorow
,eom
(end-of-month),som
(start-of-month).
- Expose folder creation time and last modified time as date fields
- Embedded Metadata, Embedded Queries:
- Embed shorthand queries using something like
dv: page.value
. - Embed metadata outside the YAML block using customizable notation.
- Add additional metadata about the current page (call it 'this') to ease templating support.
- Embed shorthand queries using something like
- Improved query debuggability:
- Show query parse + execute time on views.
- Show errors for every file that failed to be selected due to query syntax error.
- Improve parsimmon error reporting (possibly rewrite into custom recursive descent parser?)
- More parser tests.
- More complex task queries:
- Filter on a per-task, rather than per-file basis.
- Filter tasks by completion.
- Include nearby context with tasks - the header they are under, the preceding paragraph, etc.
- More query fields:
- Select file title. See
file.name
. - Select file length (in words, in bytes, etc). See
file.size
. - Select from CSV (data is selected from CSV).
- Select file title. See
- Responsive views:
- Allow automatic sorting by clicking on headers.
- Allow automatic filtering with a right-click modal.
- Add properties to query automatically via a '+' button.
- A simple query builder modal? (Something like the vantage plugin for search)
- Live Updating View (when a new query match shows up)
- Usability:
- Schema validation for objects (using a central
Schema.md
file probably)
- Schema validation for objects (using a central
- More dataviews:
- Calendar view
- Timeline view
- Gallery view (primarily for images)
- Hierarchical view
- Object view (create custom objects anywhere in a file & collect them into a list)
Contributions via bug reports, bug fixes, documentation, and general improvements are always welcome. For more major feature work, make an issue about the feature idea / reach out to me so we can judge feasibility and how best to implement it.
Have you found the Dataview plugin helpful, and want to support it? I accept donations which go towards future development efforts.