Hi, im still struggling with dataview and thus asking the 4heads here for help.
I am trying to create a little dashboard in a “home” note and my goal is to list all files that do NOT link to any file containing the tag moc.
In my MOC files i have small lists of all files related to this topic so if i missed anything, they shouldn’t be in any of these lists and therefore should appear in the query.
Thanks in advance to everyone reading this!
And yes, I looked for help already but I only found slightly different answers (like this) and since I still don’t quite understand this stuff it’s really hard for me to change/adapt code.
The queries in the linked thread assume that the query is within the moc note. If that wasn’t the case, you could use a query like this:
```dataview
LIST FROM -[[moc]]
SORT file.name ASC
```
However, in your use case this still would not work since you use an #moc tag. In order for the above query to work for you, the occurrences of the #moc tag would have to be either replaced by or supplemented with an [[moc]] link. This is easy enough to implement.
It could be accomplished using a vault wide search and replace. However, I wouldn’t recommend doing that unless you have the vault backed up. It would also be important that you consider possible unique scenarios that could cause false positives, etc. This type of operation has the possibility to cause serious problems unless you are very careful. But, to be clear, it is very possible.
So, depending upon how many notes in your vault have the #moc tag, you might consider manually reviewing all the instances that the search and replace would be applied. This can be easily done in an application such VSCode.
I am unaware of a way to create a dashboard using the #moc tag as opposed to the link. But, it very well could be possible. I am interested to see if someone else has a solution for you.
Thanks for your input, I didn’t consider that this would be problematic when scaling up the Vault but obviously it is! I’ll look around a bit more and maybe find a solution that is easy to implement whilst still being reliable and not performance breaking.
@nohell You’re welcome. I don’t mean to discourage you from using the solution I described above. I just wanted to make it extra clear that when doing a vault wide search and replace, some unexpected things could occur. I say this because I am unaware what your notes contain and what your workflow is.
But the basic result would be that all occurrences of the string #moc would be replaced with the string [[moc]]. It shouldn’t be too disastrous as long as you review each of the instances before applying it. And of course make a backup first.
@I-d-as you didn’t encourage me at all. I am just trying to find the best possible solution and based on your input it seems that my idea works, just not perfectly.
Regarding to your solution though, is there maybe a way to invert my search?
TABLE file.outlinks AS "Outlinks"
FROM #MOC
SORT file.name ASC
Also of note (from the Dataview reference) to “Find All Direct And Indirectly Linked Pages”. I imagine this code can be modified or used as reference to accomplish the goal here:
```dataviewjs
let page = dv.current().file.path;
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));
```
I ended up revising my list of pages with inlinks but no outlinks to use the dataviewjs format and for this level of complexity that is probably better than trying to coerce the SQL-like syntax into solving this.
For reference, this is how it looks now for me:
console.log(`Loading DanglingView`);
let inlinks = dv.current().file.inlinks;
let outlinkPaths = dv.current().file.outlinks?.values?.map(link => link.path) || [];
// Filter only those inlinks not included in outlinkPaths and sort them
let filtered = inlinks
.filter(inlink => !inlink.path.includes("Main Index"))
.filter(inlink => !outlinkPaths.includes(inlink.path))
.sort(inlink => inlink.path.split("/").pop());
// Split inlinks that are in the "Daily" directory and not
let dangling = filtered.filter(inlink => !inlink.path.includes("Daily"));
let dangling_dailies = filtered.filter(inlink => inlink.path.includes("Daily"));
if (dangling.length > 0) {
dv.header(5, "Dangling");
dv.list(dangling);
} else if (dangling.length === 0) {
dv.paragraph("(No dangling backlinks ...)");
}
if (dangling_dailies.length > 0) {
dv.header(5, "Dangling from daily notes")
dv.list(dangling_dailies);
}
(I am then storing this as DanglingView.js and calling it using views from different pages (basically from each MOC page):
await dv.view("Views/DanglingView")
But it can certainly be used directly, and probably better to do it that way if it is for a central page.
For me, this is now the only way to Obsidian. I throw in links to relevant MOCs as I create new pages. And at the bottom of each MOC I have this code, which immediately makes it obvious for me if I have linked to it but am not integrating it in the MOC.
I realize that this is not exactly what was sought, but I think the filtering that I’m doing there can serve as a good template for what you want to do.