Filter pages based on specific author

Hey all!

I’m trying to figure out the where clause that will let me filter based on an item’s sub-list. This is my latest attempt, but it’s failing:

{{ $author_pubs:= where (where .Site.Pages "Section" "publication") $member_id "in" "Params.Authors" }}

The inner where clause is doing the right thing, and $member_id is set right. For clarity, this code…

<pre>{{ $member_id }}</pre>
<pre>{{ where .Site.Pages "Section" "publication" }}</pre>
<pre>{{ (index (where .Site.Pages "Section" "publication") 0).Params.Authors }}</pre>

…gets rendered as:

Unfortunately, my $author_pubs is empty.

Aside from a fix to the set building above, I’d be curious as to how to debug this all better – currently I’m just guessing at parameters and re-deploying the site to check. Any tips would be greatly appreciated!

Hi there,

It is easier to help you if we can replicate your issue. Please have a read about Requesting Help .

Sure thing. I’m sure this is a simple silly thing, which is why I was hoping the syntax above was enough to show what I’ve been doing wrong. Here’s a MWE I just through together:

My ID appears on 2 of the 3 paper files: content/papers

This is the fairly empty test page (just fires up the layout): content/page/test.md

And this shows what fails: hugo-issue/test.html at main · haz/hugo-issue · GitHub

(only included the two most important links, since I’m limited to 2 URLs in a post as a new user)

I understand what’s going on with all the lines but the last. I’ve also tried a wide variety of things for the last, to no avail. Just want the list of “paper” pages that have a particular author listed. Don’t want to iterate through them all and output things as need be, because this will ultimately be wrapped in a first functionality to grab the most recent 5 papers.

Do let me know if there’s anything else I can provide!

From collections.Where | Hugo :

in

true if a given field value is included in a matching value; a matching value must be an array or a slice

The value of the field “.Params.Authors” is a list of maps, which you are trying to match against a string.

{{ $authorpapers := slice }}
{{ range $papers }}
{{ $p := . }}<!-- store current page iteration -->
    {{ with .Params.authors }}
        {{ if gt (len (where . "id" $member_id)) 0 }}
   <!-- where statement returns slice containing  matches to .Params.author[i].id == $member_id -->
   <!-- gt 0 means the paper includes this author, so store the page. -->
            {{ $authorpapers = $authorpapers | append $p }}
        {{ end }}
    {{ end }}
{{ end }}

{{ $authorpapers }}
{{ first 5 ( sort $authorpapers "Date" "desc" ) }}

Wild. I’m unfamiliar with slice, but that method of having a large block to build the right list is something I’d assumed would work, but is sub-optimal.

Ya, that makes sense. If I rewrite the targetted line, and abuse the notation to a point that obviously doesn’t parse, this is what I was after:

{{ $author_pubs:= where (where .Site.Pages "Section" "publication") $member_id "in" <current publication item's author list ID's> }}

If it was Python, then something like [author.id for author in pub.authors]. I thought apply might come to the rescue, but I couldn’t make that fly either.

So no advanced one-liner that would capture the same as the $authorpapers block you gave? Either way, thanks for all the advice!

If you have control over your content, you could use Taxonomies instead.

<!-- papers/px.md -->
authors = ["john.doe", "foo.bar"]
## config.toml
[taxonomies]
author = "authors"
<!-- content/page/test.md -->
+++
...
id: "john.doe"
+++
<!-- content/authors/john.doe/_index.md -->
+++
name = "John Doe"
is_member = true
+++
<pre>
{{ $member_id }}
{{ $author := (site.GetPage (print "authors/" $member_id)) }}
{{ $author.Params.name }} / {{ $author.Params.is_member }}
{{ $author.Pages }}
{{ where $author.Pages "Section" "papers" }}
</pre>
john.doe

John Doe / true
Pages(2)
Pages(2)

Code like that in theme widget works as expected - filtering pages by his author

{{ if $st.Params.content.filters.author }}
  {{ $archive_page = site.GetPage (printf "authors/%s" (urlize $st.Params.content.filters.author)) }}
  {{ $query = $query | intersect $archive_page.Pages }}
{{ end }}

UPD. some explanation - to get pages with any filter the simplest way is using intersect function which are have too sets as a parameters and return items which are present in both sequences. So if you can get all posts or any pages in sections or needed type/kind, after that you should retrieve ones more sequence of pages with needed params and intersect its to get common elements of both.

Hope this helps you :grinning:

Thank you both! I think I’ll run with the first option since it’s the simplest for me to grok and extend as more requirements come to the fore. Really appreciate the dive into this!