List notes that does not appear in a MOC

Hi! Can I use DataView to list all notes that none of my MOCs are linking to?

All of my MOCs have a specific tag. What I would like to do is list all notes that are not referenced by any notes with this particular tag.

Relatedly, can DataView create a table listing all of my permanent notes (#permanent) and the MOCs (#moc) that link to them?

Could you please specify some more information like what is that tag which denotes a MOC (or potentially multiple MOC’s)?

The query should be doable by doing some filtering against the outlinks of your notes, and checking if any (or none) of them are linking to a MOC file. But we need a little more information in order to build a suitable test set, to properly test such a query.

Certainly, I use the tag #moc for all of my MOCs, and my permanent notes are tagged #permanent.

It would be fantastic if I could run a query that lists all permanent notes (#permanent) not referred to in any MOC (#moc). Additionally, I was hoping it would be possible to obtain a table listing every permanent note (#permanent) and the MOCs (#moc) linking to each note.

I believe this could be beneficial for many of us who rely on MOCs to structure our network of notes. The latter table would be extremely useful for updating links between notes and MOCs over time, as MOCs evolve and (at least for me) might change levels in the note hierarchy. (It would be practical with both queries even though the last one could serve both these needs.)

I created some files:

  • MOCs: mocha, mochila, mockup
  • Permanent files: perform, peril, perms, perfect, pernickety, perplex, perfume
  • Non-MOCs: smock, hammock, drammock
  • Non permanent files: camper, super, flipper

And linked these back and forth with some kind of strategy behind that linking. At the end the one in italics in the list above where not linked from any of the MOCs.

My two end queries resulted in this output:

So this should list both of the cases you asked for, with a little extra information in the tables.

The actual queries

Permanent, not in a MOC

To get those permanent notes not linked from a MOC already I used this query:

TABLE inMoc, join(file.inlinks) as inlinks, outMoc, join(file.outlinks) as outlinks
FROM #permanent
FLATTEN list(map(file.outlinks, (f) => econtains(f.file.etags, "#moc"))) as outMoc
FLATTEN list(map(file.inlinks, (f) => econtains(f.file.etags, "#moc"))) as inMoc
WHERE none(inMoc)

It has a little bit of extra information related to file.outlinks which we don’t really need, and it could have been a LIST and just remove all the columns of extra information, but I’ve got a plan for those a little later on. For your end query, though, you could remove the stuff related to the FLATTEN ... as outMoc, and most likely change it to a simple LIST without any columns showing.

I’m using FLATTEN list(...) to build a list of which of either the inlinks or outlinks actually containing the moc tag. (Slightly better explanation comes later down in this reply). This list is built using a mapping of whether the file.etags of each link contains an exact match (hence the econtains) of the moc tag. These lists are stored in inMoc for inlinks to the permanent notes, and outMoc for outgoing links from the permanent notes. NB! Since we do want the actual lists, and not having them split up, I needed to add the list( ... ) around the map( ... ) to preserve the list.

After building these boolean lists of moc-tagging, I simply use none(inMoc) in the WHERE clause to select only permanent notes not having any inlinks from a #moc-tagged note. Please feel free to play around using any(inMoc) or all(outMoc) or similar to get a feel for the various definitions (, or just remove the WHERE clause all together to get a sense of all your permanent notes).

Permanent, with MOC origin

The other query, which is rather similar to the first query looks like this:

FROM #permanent
FLATTEN list(map(file.outlinks, (f) => econtains(f.file.etags, "#moc"))) as outMoc
FLATTEN list(map(file.inlinks, (f) => econtains(f.file.etags, "#moc"))) as inMoc
WHERE any(inMoc)
FLATTEN join(map(filter(file.inlinks, (f) => econtains(f.file.etags, "#moc")), (m) => as MOCorigin

I use the same buildup of inMoc and outMoc, but since we now want to list from which MOC the permanent is linked from, I changed the WHERE clause to any(inMoc), and then I added a new filtering operation choosing only those tagged with moc, which I then map to their respective file.links. This is the last FLATTEN thingy, which looks a lot more complex than it actually is, but here follows the slightly better explanation of what actually happens:

  • FLATTEN join( ... ) as MOCorigin – After doing the rest of the statement join together the resulting list, and store it in the MOCorigin variable, readily available for display in a column. Without this, you’d get the links in an ordinary list under each other
  • map( ... , (m) => – With the input (to be explained below), map each of the entries to its property
  • filter( file.inlinks, (f) => ... ) – This syntax, used here and for the map, is used to split up the list, aka file.inlinks, into its separate parts, and then use them as f.* in the next expression
  • econtains(f.file.etags, "#moc") – I’m using econtains to get a complete and exact match on the entirety of the tags. This is to avoid false matches towards strange tags like #smock, #not/a/moc, and so on… :-). If you used file.tags it’d split up any nested tags, which also could lead to false positives

So there you have your two queries, which is kind of simple once you get to understand them, but which do require some knowledge to build and get correct. If you’d like to explore options and test different variations, I’ve also included my complete test folder in the zip file below. (3.8 KB)

Expand this somewhere in your vault, and you can play around with these two queries, and some others displaying the test files. There are also some simple queries related to why I chose to use econtains() and file.etags. The queries are also limited to that specific folder, so they should be standalone and not interfere with your other vault information. (However, they might show up in global queries related to #permanent or moc :slight_smile: )

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.