🧠 Obsidian · & le vault autoportant

Chapitre 05
Dataview : interroger ses propres notes

Objectifs du chapitre

1. L'idée

Dataview lit le front-matter de toutes les notes du vault et t'en donne une vue de base de donnĂ©es. Tu Ă©cris une requĂȘte dans un bloc de code, et Obsidian affiche le rĂ©sultat, recalculĂ© Ă  chaque ouverture de la note.

C'est le pendant du chapitre 3 : le front-matter est le contrat, Dataview est le moteur qui l'exploite. Sans lui, un vault plat n'est qu'un tas de fichiers ; avec lui, le classement se reconstruit Ă  la demande, sous autant d'angles que tu veux.

```dataview
TABLE status, repo, updated
FROM "30-projets"
WHERE type = "project" AND status = "active"
SORT updated DESC
```

Le renversement Ă  saisir : tu ne ranges plus, tu dĂ©cris. Une note bien dĂ©crite apparaĂźt toute seule dans toutes les vues qui la concernent — et dans celles que tu inventeras dans six mois, sans avoir Ă  la dĂ©placer.

2. Les quatre formes de requĂȘte

FormeProduitQuand
LISTUne liste de liens« Quelles notes
 ? »
TABLEUn tableau, une colonne par expression « Quelles notes, et avec quelles valeurs ? »
TASKLes cases à cocher, cochables depuis la vue « Que reste-t-il à faire ? »
CALENDARUn calendrier pointé par une date Rare ; joli, peu actionnable
LIST
FROM "20-notes"
WHERE type = "concept"
SORT file.name ASC

TABLE WITHOUT ID file.link AS Note, updated AS "DerniĂšre touche"
FROM "20-notes"
LIMIT 10

TASK
FROM "30-projets"
WHERE !completed

WITHOUT ID supprime la premiĂšre colonne, ajoutĂ©e d'office, qui contient le lien vers la note. À utiliser dĂšs que tu veux maĂźtriser tes colonnes, comme ci-dessus oĂč le lien est remis Ă  la main sous un nom choisi.

3. Choisir la source

FROM restreint l'ensemble de dĂ©part. Sans lui, la requĂȘte porte sur tout le vault.

FROM "30-projets"                -- un dossier (guillemets obligatoires)
FROM #safety                      -- une étiquette
FROM [[profinet]]                 -- les notes qui pointent VERS cette note
FROM outgoing([[profinet]])       -- les notes QUE cette note cite
FROM "20-notes" AND #safety       -- combinaisons avec AND / OR / -
FROM "20-notes" AND -#Ă -trier

FROM [[une note]] mĂ©rite d'ĂȘtre connu : c'est la version interrogeable des liens retour. PlacĂ© dans une fiche projet, il liste toutes les notes quotidiennes qui l'ont citĂ©e — un journal de projet reconstituĂ© sans qu'on l'ait jamais tenu.

4. Les champs implicites

Au-delĂ  de ton front-matter, Dataview expose sur chaque note un objet file que tu n'as rien eu Ă  remplir :

ChampContenu
file.nameNom sans extension
file.linkLien cliquable vers la note
file.folderDossier parent
file.ctime / file.mtimeCréation et modification, vues par le systÚme de fichiers
file.tagsÉtiquettes, corps et front-matter confondus
file.inlinks / file.outlinksLiens entrants et sortants
file.tasksLes cases Ă  cocher de la note

file.ctime et file.mtime viennent du systĂšme de fichiers, pas de toi. Un git clone, une copie, une synchronisation les réécrivent toutes Ă  la date de l'opĂ©ration. C'est exactement pourquoi le schĂ©ma du chapitre 3 porte ses propres created et updated : eux voyagent avec le contenu.

Les champs en ligne

Dataview lit aussi des champs posés dans le corps de la note, avec un double deux-points :

Mesure effectuée le terrain. duree:: 45min
- [ ] Reprendre l'essai [échéance:: 2026-09-01]

Pratique pour annoter une ligne prĂ©cise. À utiliser avec parcimonie : ces champs Ă©chappent au front-matter, donc au contrat du chapitre 3, donc au validateur.

5. Filtrer, trier, limiter

WHERE type = "project" AND status != "closed"
WHERE contains(tags, "safety")
WHERE created >= date(2026-01-01)
WHERE length(file.inlinks) = 0
WHERE contains(projects, this.file.link)

SORT updated DESC, file.name ASC
LIMIT 20

this dĂ©signe la note qui contient la requĂȘte. C'est ce qui permet d'Ă©crire une requĂȘte gĂ©nĂ©rique dans un template : la mĂȘme ligne, recopiĂ©e dans chaque fiche projet, donne Ă  chaque fois le bon rĂ©sultat.

Les fonctions les plus utiles : contains(liste, valeur), length(liste), date(
) et dur(
), choice(test, si_vrai, si_faux), filter(), map(), sum(), round().

6. Grouper — et le piùge

GROUP BY regroupe les résultats par la valeur d'une expression. Et il change ce qui est visible à partir de là, ce que la documentation ne crie pas assez fort.

TABLE repo, updated
FROM "30-projets"
WHERE type = "project"
GROUP BY status

Cette requĂȘte s'affiche sans erreur, avec les bons groupes
 et deux colonnes intĂ©gralement vides.

AprĂšs GROUP BY, une ligne de rĂ©sultat n'est plus une note : c'est un groupe. Deux choses seulement existent Ă  ce niveau — la clĂ© du groupe (key) et rows, le tableau des notes qui le composent. repo et updated n'y sont pas dĂ©finis, donc s'affichent vides.

Il faut passer par rows :

TABLE rows.file.link AS Projet, rows.repo, rows.updated
FROM "30-projets"
WHERE type = "project"
GROUP BY status

Ce dĂ©faut est passĂ© au travers d'une revue dans le vault de la partie II : la requĂȘte s'affichait, les groupes Ă©taient corrects, et personne ne remarquait les colonnes vides. Aucun test ne peut l'attraper — seule la lecture du rĂ©sultat le rĂ©vĂšle.

FLATTEN fait l'inverse : il déplie une liste pour produire une ligne par élément. Utile pour éclater les étiquettes ou les liens d'une note.

TABLE file.link
FROM "10-journal"
FLATTEN projects AS project
WHERE project = this.file.link

7. Les trois vues du vault de référence

Dans le vault de la partie II, les vues sont des notes ordinaires rangĂ©es dans 90-meta/vues/. Elles sont donc versionnĂ©es, liables, et modifiables sans toucher Ă  la configuration.

Tableau de bord

TABLE status, repo, updated
FROM "30-projets"
WHERE type = "project" AND status = "active"
SORT updated DESC

Complété par la liste de l'inbox à trier et, via le plugin Tasks, les tùches en retard.

Concepts orphelins

LIST
FROM "20-notes"
WHERE type = "concept"
  AND length(file.inlinks) = 0
  AND (!see_also OR length(see_also) = 0)
SORT file.name ASC

C'est le dĂ©tecteur de base de connaissance qui pourrit : une fiche que rien ne cite et qui ne cite rien ne sera jamais relue. La double condition couvre les deux formes d'absence — champ inexistant, et champ prĂ©sent mais vide.

8. Dataview JS, et quand s'arrĂȘter

Dataview offre aussi un mode JavaScript, dataviewjs, oĂč tu construis le rendu Ă  la main. Il permet tout, y compris des choses qu'on regrette.

Trois raisons de rester sur le langage de requĂȘte tant que possible : le JavaScript s'exĂ©cute Ă  chaque affichage et peut ralentir sĂ©rieusement une note ; il est illisible pour qui reprend le vault ; et il permet d'Ă©crire dans le vault, donc de casser des choses depuis ce qui devrait n'ĂȘtre qu'un affichage.

Si une vue demande vraiment du JavaScript, demande-toi d'abord si le schĂ©ma de front-matter n'est pas en cause. Les neuf fois sur dix, la requĂȘte complexe compense une donnĂ©e mal structurĂ©e.

Récapitulatif

Exercices

Exercice 1 — Écrire la requĂȘte

Écris une requĂȘte qui liste, sous forme de tableau, les fiches de 20-notes touchĂ©es depuis le 1er juillet 2026, avec leur date de mise Ă  jour et leur nombre de liens entrants, les plus citĂ©es d'abord.

Voir la solution
TABLE WITHOUT ID file.link AS Fiche,
      updated AS "Mise Ă  jour",
      length(file.inlinks) AS Citations
FROM "20-notes"
WHERE type = "concept" AND updated >= date(2026-07-01)
SORT length(file.inlinks) DESC

Points d'attention : date(2026-07-01) sans guillemets — c'est un littĂ©ral de date, pas une chaĂźne ; length(file.inlinks) se rĂ©pĂšte dans la colonne et dans le tri, Dataview ne permet pas de trier sur l'alias ; et WITHOUT ID Ă©vite la colonne de lien en double.

Exercice 2 — RĂ©parer la requĂȘte

Cette requĂȘte affiche les bons groupes mais des colonnes vides. Corrige-la, et explique en une phrase pourquoi elle ne produisait aucune erreur.

TABLE title, created
FROM "20-notes"
GROUP BY type
Voir la solution
TABLE rows.file.link AS Note, rows.title, rows.created
FROM "20-notes"
GROUP BY type

Pourquoi pas d'erreur : aprĂšs GROUP BY, title et created ne sont pas des noms invalides, ce sont des champs simplement absents du contexte de groupe. Dataview traite un champ absent comme vide — comportement voulu, qui Ă©vite qu'une note sans le champ fasse planter toute la vue. Le coĂ»t, c'est qu'une faute de frappe ou une erreur de portĂ©e passe inaperçue.

Le rĂ©flexe Ă  prendre : une colonne vide sur toutes les lignes n'est pas un vault mal rempli, c'est une requĂȘte fausse.

Exercice 3 — Concevoir la vue manquante

Tu veux repĂ©rer les notes quotidiennes qui mentionnent un projet dont le status est closed — signe que tu travailles encore sur quelque chose que tu crois terminĂ©. Comment t'y prends-tu ?

Voir la solution

La difficultĂ© est que la condition porte sur une propriĂ©tĂ© de la note liĂ©e, pas de la note courante. Il faut dĂ©plier les liens puis suivre le lien :

TABLE WITHOUT ID file.link AS Jour, project AS Projet
FROM "10-journal"
FLATTEN projects AS project
WHERE project AND project.status = "closed"
SORT file.name DESC

FLATTEN produit une ligne par projet cité, puis project.status déréférence le lien pour lire le front-matter de la cible.

Le WHERE project AND 
 n'est pas décoratif : une note quotidienne sans projects produit un project nul, et déréférencer nul remonterait une erreur.

Autre approche, plus simple Ă  lire mais moins directe : partir des projets clos et lister leurs liens entrants avec FROM [[
]]. Il faudrait alors une requĂȘte par projet — d'oĂč l'intĂ©rĂȘt de la version ci-dessus, qui tient en une vue.