---
title: collections.Where
description: Returns a slice by filtering the given slice based on a key, operator, and value.
categories: []
keywords: []
params:
  functions_and_methods:
    aliases: [where]
    returnType: '[]any'
    signatures: ['collections.Where SLICE KEY [OPERATOR] VALUE']
aliases: [/functions/where]
---

The `where` function returns the given slice, removing elements that do not satisfy the comparison condition. The comparison condition is composed of the `KEY`, `OPERATOR`, and `VALUE` arguments:

```text
collections.Where SLICE KEY [OPERATOR] VALUE
                        --------------------
                        comparison condition
```

Hugo will test for equality if you do not provide an `OPERATOR` argument. For example:

```go-html-template
{{ $pages := where .Site.RegularPages "Section" "books" }}
{{ $books := where hugo.Data.books "genres" "suspense" }}
```

## Arguments

The where function takes three or four arguments. The `OPERATOR` argument is optional.

`SLICE`
: (`[]any`) A [page collection](g) or a [slice](g) of [maps](g).

`KEY`
: (`string`) The key of the page or map value to compare with `VALUE`. With page collections, commonly used comparison keys are `Section`, `Type`, and `Params`. To compare with a member of the page `Params` map, [chain](g) the subkey as shown below:

  ```go-html-template
  {{ $result := where .Site.RegularPages "Params.foo" "bar" }}
  ```

`OPERATOR`
: (`string`) The logical comparison [operator](#operators).

`VALUE`
: (`any`) The value with which to compare. The values to compare must have comparable data types. For example:

Comparison|Result
:--|:--
`"123" "eq" "123"`|`true`
`"123" "eq" 123`|`false`
`false "eq" "false"`|`false`
`false "eq" false`|`true`

When one or both of the values to compare is a slice, use the `in`, `not in`, or `intersect` operators as described below.

## Operators

Use any of the following logical operators:

`=`, `==`, `eq`
: (`bool`) Reports whether the given field value is equal to `VALUE`.

`!=`, `<>`, `ne`
: (`bool`) Reports whether the given field value is not equal to `VALUE`.

`>=`, `ge`
: (`bool`) Reports whether the given field value is greater than or equal to `VALUE`.

`>`, `gt`
: `true` Reports whether the given field value is greater than `VALUE`.

`<=`, `le`
: (`bool`) Reports whether the given field value is less than or equal to `VALUE`.

`<`, `lt`
: (`bool`) Reports whether the given field value is less than `VALUE`.

`in`
: (`bool`) Reports whether the given field value is a member of `VALUE`. Compare string to slice, or string to string.

`not in`
: (`bool`) Reports whether the given field value is not a member of `VALUE`. Compare string to slice, or string to string.
`intersect`
: (`bool`) Reports whether the given field value (a slice) contains one or more elements in common with `VALUE`.

`like`
: (`bool`) Reports whether the given field value matches the [regular expression](g) specified in `VALUE`. Use the `like` operator to compare `string` values. The `like` operator returns `false` when comparing other data types to the regular expression.

> [!NOTE]
> The examples below perform comparisons within a page collection, but the same comparisons are applicable to a slice of maps.

## String comparison

Compare the value of the given field to a [`string`](g):

```go-html-template
{{ $pages := where .Site.RegularPages "Section" "eq" "books" }}
{{ $pages := where .Site.RegularPages "Section" "ne" "books" }}
```

## Numeric comparison

Compare the value of the given field to an [`int`](g) or [`float`](g):

```go-html-template
{{ $books := where site.RegularPages "Section" "eq" "books" }}

{{ $pages := where $books "Params.price" "eq" 42 }}
{{ $pages := where $books "Params.price" "ne" 42.67 }}
{{ $pages := where $books "Params.price" "ge" 42 }}
{{ $pages := where $books "Params.price" "gt" 42.67 }}
{{ $pages := where $books "Params.price" "le" 42 }}
{{ $pages := where $books "Params.price" "lt" 42.67 }}
```

## Boolean comparison

Compare the value of the given field to a [`bool`](g):

```go-html-template
{{ $books := where site.RegularPages "Section" "eq" "books" }}

{{ $pages := where $books "Params.fiction" "eq" true }}
{{ $pages := where $books "Params.fiction" "eq" false }}
{{ $pages := where $books "Params.fiction" "ne" true }}
{{ $pages := where $books "Params.fiction" "ne" false }}
```

## Member comparison

Compare a [`scalar`](g) to a [`slice`](g).

For example, to return a slice of pages where the `color` page parameter is either "red" or "yellow":

```go-html-template
{{ $fruit := where site.RegularPages "Section" "eq" "fruit" }}

{{ $colors := slice "red" "yellow" }}
{{ $pages := where $fruit "Params.color" "in" $colors }}
```

To return a slice of pages where the `color` page parameter is neither `red` nor `yellow`:

```go-html-template
{{ $fruit := where site.RegularPages "Section" "eq" "fruit" }}

{{ $colors := slice "red" "yellow" }}
{{ $pages := where $fruit "Params.color" "not in" $colors }}
```

## Intersection comparison

Compare a `slice` to a `slice`, returning elements with common values. This is frequently used when comparing taxonomy terms.

For example, to return a slice of pages where any of the terms in the `genres` taxonomy are "suspense" or "romance":

```go-html-template
{{ $books := where site.RegularPages "Section" "eq" "books" }}

{{ $genres := slice "suspense" "romance" }}
{{ $pages := where $books "Params.genres" "intersect" $genres }}
```

## Regular expression comparison

To return a slice of pages where the `author` page parameter begins with either "victor" or "Victor":

```go-html-template
{{ $pages := where .Site.RegularPages "Params.author" "like" `(?i)^victor` }}
```

{{% include "/_common/functions/regular-expressions.md" %}}

> [!NOTE]
> Use the `like` operator to compare string values. Comparing other data types will result in an empty slice.

## Date comparison

### Predefined dates

There are four predefined front matter dates: [`date`][], [`publishDate`][], [`lastmod`][], and [`expiryDate`][]. Regardless of the front matter data format (TOML, YAML, or JSON) these are [`time.Time`][] values, allowing precise comparisons.

For example, to return a slice of pages that were created before the current year:

```go-html-template
{{ $startOfYear := time.AsTime (printf "%d-01-01" now.Year) }}
{{ $pages := where .Site.RegularPages "Date" "lt" $startOfYear }}
```

### Custom dates

With custom front matter dates, the comparison depends on the front matter data format (TOML, YAML, or JSON).

> [!NOTE]
> Using TOML for pages with custom front matter dates enables precise date comparisons.

With TOML, date values are first-class citizens. TOML has a date data type while JSON and YAML do not. If you quote a TOML date, it is a string. If you do not quote a TOML date value, it is [`time.Time`][] value, enabling precise comparisons.

In the TOML example below, note that the event date is not quoted.

```md {file="content/events/2024-user-conference.md"}
+++
title = '2024 User Conference"
eventDate = 2024-04-01
+++
```

To return a slice of future events:

```go-html-template
{{ $events := where .Site.RegularPages "Type" "events" }}
{{ $futureEvents := where $events "Params.eventDate" "gt" now }}
```

When working with YAML or JSON, or quoted TOML values, custom dates are strings; you cannot compare them with `time.Time` values. String comparisons may be possible if the custom date layout is consistent from one page to the next. To be safe, filter the pages by ranging over the slice:

```go-html-template
{{ $events := where .Site.RegularPages "Type" "events" }}
{{ $futureEvents := slice }}
{{ range $events }}
  {{ if gt (time.AsTime .Params.eventDate) now }}
    {{ $futureEvents = $futureEvents | append . }}
  {{ end }}
{{ end }}
```

## Nil comparison

To return a slice of pages where the "color" parameter is present in front matter, compare to `nil`:

```go-html-template
{{ $pages := where .Site.RegularPages "Params.color" "ne" nil }}
```

To return a slice of pages where the "color" parameter is not present in front matter, compare to `nil`:

```go-html-template
{{ $pages := where .Site.RegularPages "Params.color" "eq" nil }}
```

In both examples above, note that `nil` is not quoted.

## Nested comparison

These are equivalent:

```go-html-template
{{ $pages := where .Site.RegularPages "Type" "tutorials" }}
{{ $pages = where $pages "Params.level" "eq" "beginner" }}
```

```go-html-template
{{ $pages := where (where .Site.RegularPages "Type" "tutorials") "Params.level" "eq" "beginner" }}
```

## Portable section comparison

Useful for theme authors, avoid hardcoding section names by using the `where` function with the [`MainSections`][] method on a `Site` object.

```go-html-template
{{ $pages := where .Site.RegularPages "Section" "in" .Site.MainSections }}
```

With this construct, a theme author can instruct users to specify their main sections in their project configuration:

{{< code-toggle file=hugo >}}
mainSections = ['blog','galleries']
{{< /code-toggle >}}

If `mainSections` is not defined in your project configuration, the `MainSections` method returns a slice with one element---the top-level section with the most pages.

## Boolean/undefined comparison

Consider this project structure:

```tree
content/
├── posts/
│   ├── _index.md
│   ├── post-1.md  <-- front matter: exclude = false
│   ├── post-2.md  <-- front matter: exclude = true
│   └── post-3.md  <-- front matter: exclude not defined
└── _index.md
```

The first two pages have an "exclude" field in front matter, but the last page does not. When testing for _equality_, the third page is _excluded_ from the result. When testing for _inequality_, the third page is _included_ in the result.

### Equality test

This template:

```go-html-template
<ul>
  {{ range where .Site.RegularPages "Params.exclude" "eq" false }}
    <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li>
  {{ end }}
</ul>
```

Is rendered to:

```html
<ul>
  <li><a href="/posts/post-1/">Post 1</a></li>
</ul>
```

This template:

```go-html-template
<ul>
  {{ range where .Site.RegularPages "Params.exclude" "eq" true }}
    <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li>
  {{ end }}
</ul>
```

Is rendered to:

```html
<ul>
  <li><a href="/posts/post-2/">Post 2</a></li>
</ul>
```

### Inequality test

This template:

```go-html-template
<ul>
  {{ range where .Site.RegularPages "Params.exclude" "ne" false }}
    <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li>
  {{ end }}
</ul>
```

Is rendered to:

```html
<ul>
  <li><a href="/posts/post-2/">Post 2</a></li>
  <li><a href="/posts/post-3/">Post 3</a></li>
</ul>
```

This template:

```go-html-template
<ul>
  {{ range where .Site.RegularPages "Params.exclude" "ne" true }}
    <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li>
  {{ end }}
</ul>
```

Is rendered to:

```html
<ul>
  <li><a href="/posts/post-1/">Post 1</a></li>
  <li><a href="/posts/post-3/">Post 3</a></li>
</ul>
```

To exclude a page with an undefined field from a boolean _inequality_ test:

1. Create a slice using a boolean comparison
1. Create a slice using a nil comparison
1. Subtract the second slice from the first slice using the [`collections.Complement`][] function.

This template:

```go-html-template
{{ $p1 := where .Site.RegularPages "Params.exclude" "ne" true }}
{{ $p2 := where .Site.RegularPages "Params.exclude" "eq" nil }}
<ul>
  {{ range $p1 | complement $p2 }}
    <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li>
  {{ end }}
</ul>
```

Is rendered to:

```html
<ul>
  <li><a href="/posts/post-1/">Post 1</a></li>
</ul>
```

This template:

```go-html-template
{{ $p1 := where .Site.RegularPages "Params.exclude" "ne" false }}
{{ $p2 := where .Site.RegularPages "Params.exclude" "eq" nil }}
<ul>
  {{ range $p1 | complement $p2 }}
    <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li>
  {{ end }}
</ul>
```

Is rendered to:

```html
<ul>
  <li><a href="/posts/post-1/">Post 2</a></li>
</ul>
```

[`MainSections`]: /methods/site/mainsections/
[`collections.Complement`]: /functions/collections/complement/
[`date`]: /methods/page/date/
[`lastmod`]: /methods/page/lastmod/
[`time.Time`]: https://pkg.go.dev/time#Time
