hugo icon indicating copy to clipboard operation
hugo copied to clipboard

Improve eq operator in where function

Open jmooring opened this issue 1 year ago • 7 comments

Use case 1: find all pages where tags equals ['foo']. Use case 2: find all pages where tags equals ['foo','bar'].

This is not possible today. You can find all pages where these tags intersect a provided slice, but you cannot compare slices with the eq operator.

The eq operator does work if your front matter is a scalar, e.g.,

title = 'something 1`
tags = 'foo'

But you can't do this:

title = 'something 2`
tags = ['foo']

You should be able to get both of the pages above with:

{{ where .Pages "Params.tags" eq "foo" }} OR
{{ where .Pages "Params.tags" eq "foo" (slice "foo"}} 

jmooring avatar Jul 26 '23 15:07 jmooring

Use case 1: find all pages where tags equals ['foo']. Use case 2: find all pages where tags equals ['foo','bar'].

The above is rather technical use cases ...

I can understand if you want to find all pages tagged with foo, but finding all pages which has the tags foo and bar and only those, that's not a use case I have seen.

Note that Go cannot compare slices directly, so it would be a fairly costly operation if implemented.

bep avatar Jul 26 '23 15:07 bep

finding all pages which has the tags foo and bar and only those, that's not a use case I have seen

I'm fine with with limiting to one tag. The specific example is:

content/
├── publications/
│   ├── publication-1.md   <-- authors = ['John', 'Richard', 'Harold']
│   ├── publication-2.md   <-- authors = ['John', 'Richard']
│   └── publication-3.md   <-- authors = ['John']
└── _index.md

Find all publications where John is the only author. (common) Find all publications where John and Richard are the only authors. (less common)

jmooring avatar Jul 26 '23 15:07 jmooring

Go 1.21 introduced the slices package which contains https://pkg.go.dev/slices#Equal.

jmooring avatar Feb 18 '24 16:02 jmooring

Go 1.21 introduced the slices package which contains https://pkg.go.dev/slices#Equal.

The functional part of this has never been the challenge. If you look at that implementation you will find a ... loop.

bep avatar Feb 18 '24 17:02 bep

Understood. Will stick with...

{{ $p := where site.RegularPages "Params.tags" "intersect" (slice "a" "b") }}
{{ range $p }}
  {{ if eq (len .Params.tags) 2 }}
    <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2>
  {{ end }}
{{ end }}

jmooring avatar Feb 18 '24 17:02 jmooring

To be clear:

tags = ['foo', 'bar']

{{ where .Pages "Params.tags" eq (slice "foo" "bar" }}

Would be cheapish to implement with strict ordering (['foo', 'bar'] != ['bar', 'foo']), but I'm not sure how useful that would be.

bep avatar Feb 18 '24 17:02 bep

I agree that strict ordering limits its usage; not sure I'd pursue it.

jmooring avatar Feb 18 '24 18:02 jmooring