A list containing tiddlers with the same tags as current tiddler?

Hi All,

I’m trying to build a list on a tiddler that lists all tiddlers that have the same tags as the current one.

The details:
Tiddler A with tags: [[topic a]] [[topic b]]
Tiddler B with tags: [[topic b]] [[topic c]]
Tiddler C with tags: [[topic a]] [[topic b]]
Tiddler D with tags: [[topic a]] [[topic b]]

My goal is to put a list on Tiddler A that would look like:
Tiddler C
Tiddler D

C and D have the same tags as A so they should be in the list. No need to list A again in the list so that should be removed from the list.

Trying to figure out how to compare tags like that. Also, I wrote the example like that because the tags might contain spaces.

Any pointers or code to help me along the path would be helpful.
Thanks,
Scott

Maybe …

<$vars hits={{{ [<currentTiddler>tags[]count[]] }}}>
<$list filter="[<currentTiddler>tags[]tagging[]]-[<currentTiddler>]" variable="eligible" >
<$list filter="[<eligible>tags[]] :intersection[<currentTiddler>tags[]] +[count[]compare:number:eq<hits>]" variable="rem"  >
<<eligible>><br/>
</$list></$list>
</$vars>
1 Like

You beat me to the punch, Mark.

My version:

<$vars theseTags={{{ [[Tiddler A]tags[]sort[]join[,]] }}} >

<$list filter="[all[tiddlers]] :filter[tags[]sort[]join[,]match<theseTags>] +[!match<currentTiddler>]">
<$link/>
</$list>

</$vars>

1 Like

Oops, forgot to replace that “[Tiddler A]” reference with <currentTiddler>,

so theseTags should look like:

theseTags={{{ [<currentTiddler>tags[]sort[]join[,]] }}}

Thanks, Charlie and Mark! Both of these provide similar and different solutions. Interestingly I might end up using both as I test for a bit.

I threw together a demo wiki in case future searchers can benefit:
Tiddlywiki Example — A list of tiddlerys tagged the same as the current tiddler (techlifeweb.com)

I am a beginner. I want to list all the tiddles with the same tag.
But I can’t understand these codes.
Shall I create a new topic?

@pkuadt The answer exists already in this thread but your question seems the same as this topic.

To list all the tiddlers with the same tag you need a filter. See filter Operators on TiddlyWiki.com, scroll down to “Tag Operators”.

The First is “tag” filter the input by tag

  • All filters by default start with “all[]” but lets include that
  • Filter "[all[]tag[tagname]]"

Examples use in tiddler on tiddlywiki.com
{{{ [all[]tag[Tag Operators]] }}}

<$list filter="[all[]tag[Tag Operators]]">

</$list>

If you expect other tiddlers to display look at the all operator examples.

I really really appreciate for your kindness.

So I’ve been hacking around on the example page. Turns out I’d like the including-but-partial tag filtering behaviour of the @Mark_s solution with the single filter of the @Charlie_Veniot answer. Is this possible? I’ve been chopping the code around for hours but have nothing worthy to show!

Also I’d like to show a simple count of the number of matches delivered by the filter at the top of my output but in the @Mark_s solution the iterative nature means there is no place to catch the count value and the display prints repeatedly.

The situation often comes up where you can only get an answer one item at a time. Meaning that you can’t do an all-up count. The filter syntax isn’t a complete language IMO, so it’s not always going to be possible to do everything on a single line.

One solution is to capture the results in a wikify widget, then reparse them as a single filter line. The code below should work, as long as you haven’t perversely created titles with triple semi-colons in them.

Note that Charlie and I made slightly different assumptions. I assumed that the tiddlers being counted might eventually have other tags applied. Charlie assumed that we were looking for an exact identical set of tags to the current tiddler.

\define item()
<$vars hits={{{ [<currentTiddler>tags[]count[]] }}}><$list filter="[<currentTiddler>tags[]tagging[]]-[<currentTiddler>]" variable="eligible" ><$list filter="[<eligible>tags[]] :intersection[<currentTiddler>tags[]] +[count[]compare:number:eq<hits>]" variable="rem"  ><<eligible>>;;;</$list></$list></$vars>
\end

<$wikify text=<<item>> name="items">
<<items>>
Count: <$count filter="[<items>split[;;;]!is[blank]]"/><br/>
<$list filter="[<items>split[;;;]]">

</$list>
</$wikify>

Well thanks @Mark_S, that’s ingenious. It works over at the example site, but I notice it’s very sensitive to the contents of the item() macro being presented as one long concatenated string, trying to break it onto different lines for a clearer view changes the behaviour?!?!

I tried it on my Bob server (Tiddlywiki version 5.2.3, Firefox 118.01) where I want to implement the filter and it gave odd output to the screen in the form:

\define item() ThisTiddler;;;ThatTiddler;;;TheOtherTiddler;;; \end

Count: 0

Not sure I trust it.

I’m also having trouble accessing the fields of <<eligible>> in filters, for example this {{{ [<eligible>{!!narrative}] }}} prints to screen the expected value held in the field but this <$link to={{{ [narrative<<eligible>!!narrative>tag[lead]] }}} /> gives a link to $:/library/sjcl.js which is not what I’m expecting.

Surely there must be another way?

1 Like

Yes, it is. So be sure your version at Bob didn’t insert line breaks or spaces.

Generally, the trick here is to use the get operator.

[<eligible>get[narrative]]

If I go to my development site Tag Filtering open that tiddler for editing and then near the bottom after the line Exclude: <<pick-tag exclude>> paste in this code;

\define item()
<$vars hits={{{ [<storyTiddler>get[include]enlist-input[]count[]] }}}><$list filter="[<storyTiddler>get[include]enlist-input[]tagging[]]-[<storyTiddler>] :except[<storyTiddler>get[exclude]enlist-input[]tagging[]] :filter[get[created]compare:string:gteq<start>compare:string:lteq<end>] :sort[get[created]]" variable="eligible" ><$list filter="[<eligible>tags[]] :intersection[<storyTiddler>get[include]enlist-input[]]+[count[]compare:number:eq<hits>]" variable="rem" ><<eligible>>;;;</$list></$list></$vars>
\end

<$wikify text=<<item>> name="items">
<<items>>
Count: <$count filter="[<items>split[;;;]!is[blank]]"/><br/>
<$list filter="[<items>split[;;;]]">
<$link to={{{ [<currentTiddler>get[narrative]tag[azalea]] }}} />
</$list>
</$wikify>

then I get the improper output:

\define item() 20170415_Bodnant_135907.jpg;;; \end

Count: 0

This tiddler has the filtering functionality I’m trying to ‘upgrade’. And the filter logic above does just what is needed; included tags are a combined requirement and all must be present, but the selected tiddler may also have other tags. Specified exclusion tags are individually subtractive.

I just need to get it to run properly and then access the fields to build the output.

All macro definitions must occur before any renderable wikitext content.

You need move the \define item() ... macro definition so it before this line:

<!-- https://kixam.github.io/TW5-datePicker/ -->

enjoy,
-e

1 Like

As Eric mentions, you have to put all the macro stuff together. Once you start text outside of a macro, TW assumes you’re now into the main body of your tiddler and stops looking for macros.

Also, you need to change “storyTiddler” to “currentTiddler”. In all the time I’ve been doing TW, I don’t recall ever using “storyTiddler”. I’m sure it has some good uses, but in this case it disappears inside the Wikify widget.

\define item()
<$vars hits={{{ [<currentTiddler>get[include]enlist-input[]count[]] }}}><$list filter="[<currentTiddler>get[include]enlist-input[]tagging[]]-[<currentTiddler>] :except[<currentTiddler>get[exclude]enlist-input[]tagging[]]
:filter[get[created]compare:string:gteq<start>compare:string:lteq<end>] 
:sort[get[created]]" variable="eligible" ><$list filter="[<eligible>tags[]] :intersection[<currentTiddler>get[include]enlist-input[]]+[count[]compare:number:eq<hits>]" variable="rem" ><<eligible>>;;;</$list></$list></$vars>
\end

Then put your output text somewhere inside your let widget where start is defined. I’ve written it like this for the moment:

<$wikify text=<<item>> name="items">
Count: <$count filter="[<items>split[;;;]!is[blank]]"/><br/>
<$list filter="[<items>split[;;;]]">
<<currentTiddler>> <br/>
</$list>
</$wikify>

The problem with your Link widget is … I don’t know how it’s supposed to work. The tiddler tagged “azalea” doesn’t have a matching narrative field. So to prove that the code works I took out the link.

It looks like you’re building a nice travelogue there!

Thanks so much for taking the time to look.

I’ve implemented the recommendations; repositioned the \define item() ... macro and used the <currentTiddler> instead of <storyTiddler> and the Count now registers…but I still can’t get the filter to function and deliver a link.

<$link to={{{ [<currentTiddler>get[narrative]tag[azalea]] }}} />

The tag azalea was chosen to demonstrate a desired functionality and because it is only carried by one tiddler in the wiki. That tiddler 20170415_Bodnant_135907.jpg does have a narrative field with the value 72b9d83e-ae69-43f0-8461-5cfd021345f4

To briefly explain the intention; related items are grouped using a uuid stored in the field narrative. So all the component tiddlers which comprise a particular visual narrative can be collected. What the demonstration filter is trying to achieve is to form a link to an individual member of a group bearing a particular tag, in this case azalea.

We’re so close…

Try this:

<$link to={{{ [tag[azalea]narrative{!!narrative}] }}} />

The to param will be the first tiddler that is

  • tagged with “azalea” AND
  • has a narrative field that has the same value as the narrative field of the current tiddler

enjoy,
-e

1 Like

Everyone, thanks for your help. I have pushed the changes discussed above to my demo which is now functioning well.

There is one slight issue in the rendering I can’t solve. On the ‘Tag Filtering’ tiddler this extraneous link, marked in red, needs to not be there. It’s somehow related to the link embedded into the image.

1 Like

Hi @TechTangle

The bug is here:

Replace /> with > and it’s gone!

Fred

1 Like