Data files and selecting using where

Hi,

I have been looking at Mike Dane’s tutorial on data files with Hugo and I have the range working when I want to loop through the list without a problem but when I try and just select one bit of data (say on a single.html page) I cannot get the “where” working.

This is his code:

{{ range $.Site.Data.states where "name" eq .title }}
	<h2>{{ .name }}</h2>
	<p>{{ .capital }}</p>
	Location : {{ .lat }}, {{ .long }}
{{end}}

But I constantly get these errors

execute of template failed at <$.Site.Data.states>: states is not a method but has arguments

The data file I’m using is data/states.json with this content

{
    "AL": {
        "name": "Alabama",
        "capital": "Montgomery",
        "lat": "32.361538",
        "long": "-86.279118"
    },
    "AK": {
        "name": "Alaska",
        "capital": "Juneau",
        "lat": "58.301935",
        "long": "-134.419740"
    }
}

Does anyone have any idea where I’m going wrong?

Thanks

Al

The signature for the where function is:

where COLLECTION KEY [OPERATOR] MATCH

You did not include the collection in call.

But that’s not really the problem here. The data structure is an object, not an array.

To directly access the details for the state of Alaska:

{{ with site.Data.states.AK }}
  <h2>{{ .name }}</h2>
  <p>{{ .capital }}</p>
{{ end }}

OR

{{ with index site.Data.states "AK" }}
  <h2>{{ .name }}</h2>
  <p>{{ .capital }}</p>
{{ end }}

If you don’t know the key, and need to use the where function to find by name, you’ll need to create a different data structure (an array). This will do that, eating the outer keys:

{{ $details := slice }}
{{ range site.Data.states }}
  {{ $details = $details | append . }}
{{ end }}

Let’s see what the new data structure looks like

<pre>{{ jsonify (dict "indent" "  ") $details }}</pre>

That gives us:

[
  {
    "capital": "Juneau",
    "lat": "58.301935",
    "long": "-134.419740",
    "name": "Alaska"
  },
  {
    "capital": "Montgomery",
    "lat": "32.361538",
    "long": "-86.279118",
    "name": "Alabama"
  }
]

Now we can do:

{{ range where $details "name" "Alaska" }}
  <h2>{{ .name }}</h2>
  <p>{{ .capital }}</p>
{{ end }}

The example above queries the data before you range through it, which is a good idea with a large data set. With a smaller data set, you could conditionally include the data while you range through it:

{{ range site.Data.states }}
  {{ if eq .name "Alaska" }}
    <h2>{{ .name }}</h2>
    <p>{{ .capital }}</p>
  {{ end }}
{{ end }}
2 Likes