Filtering pages with the in operator fails

Recently I created a website for my wife for her paintings as my first Hugo project. A really nice experience. Among other things, I created a small tool for creating labels for here painting and drawings. For that purpose, I added a property in the front matter of each page describing the painting indicating if the painting should be part of the exhibition or not. From a data modelling perspective, that was not a very sensible nor scalable approach, so I have extracted all information about exhibitions and instead placed in a data file.

The approach is pretty simple:

$exibitionPages := where site.RegularPages .Params.id “in” $exibitionArray

but instead, it filters out all pages. Note the shortcode makelabels are called from the pages ark1, ark2 and ark3 page located in contents/tools folder.

  • I have used the same idea on another page on the site. However, instead of using the in operator, I use the in function.

Problem 1

Change this:

{{ $exibitionPages := where site.RegularPages .Params.id "in" $exibitionArray }}

to

{{ $exibitionPages := where site.RegularPages "Params.id "in" $exibitionArray }}

Problem 2

When Hugo unmarshals JSON data (data/udstilling.json), the numbers (ids) are of type float64. But Params.id is an int. So your where clause is comparing different types, resulting in an empty set.

Two options:

1) Use a different format for your data file, either TOML or YAML.

2) Cast all of the elements in the array to type int using apply

{{ $exibitionArray := union .Site.Data.udstilling.painting .Site.Data.udstilling.drawing }}
{{ $exibitionArray = apply $exibitionArray "int" "." }}

Thanks a lot, that worked beautifully, although I am still a bit confused. I understand that Hugo unmarshals the numbers to float64 and I, therefore, have to coerce the types int. What I am confused about is that using the in function, I can still test for membership of the array as shown in

{{ if in site.Data.udstilling.painting .Params.id }}

which can be found in line 22 in https://github.com/stavnstrup/la-art/blob/master/layouts/shortcodes/assetlist.html

You are correct.

{{ in (slice (float 1)) (int 1) }} --> true

The where function’s in operator is handled differently than the in function.

About 6 months ago we fixed some where function type mismatches related to strings:
https://github.com/gohugoio/hugo/pull/8461. Perhaps we need to make similar accommodations for integer/float comparisons, thought I don’t know how feasible that is.

This demonstrates the problem:

{{ where (slice (dict "a" (int 1))) "a" "in" (slice (int 1)) | len }} --> 1
{{ where (slice (dict "a" (int 1))) "a" "in" (slice (float 1)) | len }} --> 0