Finding tiddlers with only one tag

Is there a way to write a filter to find all tiddlers having one specific tag and no others? So if Tiddler A has tags [[A]] and Tiddler B has tags [[A]] [[B]] only tiddler A would match?

While the tags field is normally used to hold a space-separated, bracketed list of one or more tags, it can also be treated as just another regular field containing a text value. For your purposes, you can simply compare the entire tags field value with the desired value.

For example, at https://TiddlyWiki.com, put this in a tiddler:

<$list filter="[field:tags[Welcome]]"><$link/><br></$list>

The result does NOT list “GettingStarted” and “Community”, since those tiddlers each have more than just the “Welcome” tag. However, you might notice that the tiddlers are not listed in the same order as when using the [tag[Welcome]] filter to show all tiddlers that have at least the “Welcome” tag and possibly other tags.

This is because the [tag[...]] filter operator uses a more complex set of rules to determine the order of the results. See Order of Tagged Tiddlers for details.

To achieve the same order as the [tag[Welcome] filter, but only have that one tag, you can write this:

<$list filter="[tag[Welcome]] :filter[field:tags[Welcome]]"><$link/><br></$list>

This will first get all tiddlers tagged with Welcome, using the Order of Tagged Tiddlers rules, and then filter that result to retain those tiddlers that have only that one specific tag, while preserving the same tiddler order.

Another note: if the tag value contains spaces, then the value stored in the tags field will include doubled square brackets surrounding the tag value. However, since literal filter operand values cannot contain square brackets (because they are used by the filter syntax itself), a workaround is needed by using a variable to hold the desired tag value, like this:

<$let tagvalue="Tag With Spaces">
<$list filter="[field:tags<tagvalue>]"><$link/><br></$list>
</$let>

or, for the second syntax example, we can change the :filter[...] filter run without needing a variable, like this:

<$list filter="[tag[Tag With Spaces]] :filter[enlist{!!tags}count[]match[1]]"><$link/><br></$list>

enjoy,
-e

6 Likes

Thanks, this really helped. The last syntax is what I was after because I was plugging the filter into Advanced Search and was looking for a tag with spaces in the name, making the other forms a little more awkward.