Start with YAML and inline fields, distinguish pages, tasks, and the four output types, then work through sources, conditions, sorting, and expressions.
First, distinguish body text, fields, and queries#
Content written in a note does not automatically become a field you can filter. Dataview indexes file information, lists, and tasks, and can read explicitly annotated properties; ordinary body text is still primarily understood through reading and full-text search. To find “projects that are still active and have a high priority,” first record status and priority as structured data. [1]
DQL stands for Dataview Query Language. It uses LIST, TABLE, TASK, and CALENDAR to specify the result format, then organizes results with sources, conditions, and sorting. The examples below use a fictional Studio vault: projects live in Studio/Projects and reading records in Studio/Library. They illustrate the syntax and have not been run against a real vault. Before using these queries, you need Dataview enabled in Obsidian; this website displays the code but does not execute it.
Give each record consistent fields first#
The following is the beginning of the hypothetical project Studio/Projects/Atlas.md. YAML frontmatter must be at the top of the file and uses a single colon to define fields. status is text, priority is a number, archived is a boolean, and topics is a list; due uses an ISO date. Do not put “high” in a numeric field and then compare it numerically, or mix dates and descriptions such as “next week” in the same field. [7]
---
type: project
status: active
priority: 3
archived: false
due: 2030-05-12
topics:
- search
- interface
tags:
- demo/project
---
# Atlas
reviewed:: 2030-05-02
这轮原型的 [confidence:: 4],还需要补一组边界条件。
- [ ] 检查空结果页面 [due:: 2030-05-10]Inline fields in the body use a double colon. On a standalone line, write reviewed:: value; when embedding a field in a sentence or task, use square brackets. Frontmatter describes the entire page, while [due:: ...] on a task describes that particular task. Both can be used together, but avoid casually recording the same fact in multiple places and expecting the plugin to decide which one is up to date. [1]
The examples consistently use lowercase English field names to make copying, searching, and maintenance more reliable. Dataview supports Chinese field names; fields with spaces also have normalized names or can be accessed through row. Chinese column labels displayed to readers can be defined with AS in the query; data keys do not need to handle presentation.
The file fields that already exist without manual entry#
| Field | What it tells you |
|---|---|
file.name / file.link | The file’s name and how to return to the original note |
file.folder | The directory containing the note within the vault |
file.ctime / file.mtime | The file’s creation and last-modification timestamps, including the time of day |
file.cday / file.mday | The date portions of those timestamps |
file.tags / file.etags | Tags with parent tags expanded, and only explicitly written tags |
file.tasks | The list of tasks indexed on the page |
These implicit fields are grouped in the file object; you do not have to declare them in YAML first. If a note uses #demo/project, file.tags includes both the parent #demo and the full tag; file.etags retains the explicit tags. Decide which kind you want to count before calculating tag statistics, or parent categories will also appear in the results. [2]
Modification times are useful for answering “which files changed recently,” but do not directly represent “what I learned recently.” Formatting, synchronization, and property changes can also affect file timestamps. For meaningful reading-completion or review dates, use explicit fields such as date_finished and reviewed rather than guessing from file times.
Four output types, with different units of querying#
LIST, TABLE, and CALENDAR operate on pages; TASK operates on tasks. Giving the same data a different heading does not mean the query’s level has changed. [3]
```dataview
LIST status
FROM "Studio/Projects"
```LIST displays page links by default, with status as an additional value after the link. It works well for lists; use TABLE to compare several properties at once. TABLE already includes an identifier column by default, so the example below only needs to specify status and priority. AS changes the display name, not the field name in the source note.
```dataview
TABLE status AS "状态", priority AS "优先级"
FROM "Studio/Projects"
```If you want to control the first column yourself, write TABLE WITHOUT ID file.link AS "Project", status AS "Status". The link is explicitly added back here; otherwise, readers see only property values and have difficulty returning to the record.
```dataview
TASK
FROM "Studio/Projects"
WHERE !completed AND due = date(today)
```This TASK query lists incomplete tasks due today, provided each task has a recognizable due date. A to-do without a due date will not automatically appear in today’s list merely because it is incomplete.
```dataview
CALENDAR due
FROM "Studio/Projects"
WHERE due != null
```CALENDAR places pages on a calendar according to a date; it does not draw a task Gantt chart here. Pages without dates cannot be positioned. If you need to examine task due dates, first distinguish task-level data from page-level data rather than combining the two kinds of due in one column.
Combining FROM sources: Decide between intersection and union first#
FROM limits the initial scope. A folder source uses the full path relative to the vault root and includes subfolders; enclose it in double quotes and omit the trailing slash. Tag sources use #, and link sources can use relationships between pages. [4]
| Source syntax | Meaning |
|---|---|
FROM "Studio/Projects" | Pages in this folder and its subfolders |
FROM #demo/project | Pages using this tag or its subtags |
FROM [[Atlas]] | Pages linking to Atlas |
FROM outgoing([[Atlas]]) | Pages that Atlas links to |
```dataview
LIST
FROM "Studio/Projects" AND #demo/project
WHERE archived = false
```AND requires both sides to match, producing an intersection; OR requires either side to match, producing a union. The previous example requires pages to be “in the projects folder and have the project tag.” Changing it to OR also includes pages outside the folder that have the tag. For exclusion, write #demo/project AND !#demo/retired. When combining several sources, use parentheses to make the scope explicit, for example ("Studio/Projects" OR "Studio/Library") AND !#demo/retired.
Source syntax and ordinary field expressions each have their place. FROM #demo/project selects a tag source; WHERE status = "active" filters record fields. Do not put the latter into FROM or copy the # syntax of tag sources into text-field values.
Filter, sort, and limit in the order your question requires#
```dataview
TABLE status AS "状态", priority AS "优先级", due AS "到期日"
FROM "Studio/Projects"
WHERE status = "active" AND priority >= 2
SORT priority DESC, due ASC
LIMIT 5
```First find projects that are active and have a priority of at least 2, then sort by priority in descending order. Within the same priority, sort by due date in ascending order, and finally take five results. DESC means largest to smallest; ASC means smallest to largest. If due dates are essential to the decision, also add due != null and inspect projects with missing dates separately.
Data commands are processed in the order written. Placing LIMIT before SORT selects a subset first and then sorts it, so it cannot guarantee the top five from the entire candidate set. Just as placing WHERE before or after grouping processes differently shaped data, the order itself is part of the query’s meaning. [5]
Boolean conditions must also distinguish “explicitly false” from “missing a value.” WHERE archived = false requires the value to be false; WHERE !archived may also include missing values. When field completeness is unknown, first display the raw values in a TABLE and then choose the condition. This makes data problems easier to spot than immediately treating every missing value as “not archived.”
Functions improve presentation; they do not replace data conventions#
```dataview
TABLE default(status, "待补状态") AS "状态",
choice(priority >= 3, "优先处理", "正常排队") AS "提示",
join(topics, ", ") AS "主题"
FROM "Studio/Projects"
```default supplies a fallback display value when a value is null; choice selects between two results based on a condition; join combines a list into text. They make tables easier to read, but do not write “status pending” back to YAML or determine the project’s actual status for you. [6]
Other string functions include lower, upper, and startswith. contains has different meanings for different types: with a list, it can test membership; with text, it can look for a substring. Keep lists such as topics consistent across notes rather than using a YAML list in one and a single comma-separated text value in another. Mathematical expressions also need numeric inputs. For example, a discounted budget can be written as price * 0.9; you cannot first store price as “about one hundred yuan” and expect the same calculation.
When a query is empty, check it in the smallest steps: keep only LIST and FROM to verify the source, temporarily use TABLE to display status, priority, and due, then add WHERE, SORT, and LIMIT back one at a time. A page outside the source, an unindexed field, inconsistent types, and overly strict conditions all appear as “no results,” but each needs a different fix.
References & further reading
- Dataview: Adding metadata ↗
- Dataview: Implicit page fields ↗
- Dataview: The four query types ↗
- Dataview: Query sources ↗
- Dataview: Data commands and their order ↗
- Dataview: Function reference ↗
- Dataview: Field types ↗
Adapted from technical notes. Examples use generic names.