collections.Where
where 函數會返回給定的集合,並移除不滿足比較條件的元素。比較條件由 KEY、OPERATOR 和 VALUE 參數組成:
collections.Where COLLECTION KEY [OPERATOR] VALUE
--------------------
比較條件
如果沒有提供 OPERATOR 參數,Hugo 會測試等值比較。例如:
{{ $pages := where .Site.RegularPages "Section" "books" }}
{{ $books := where .Site.Data.books "genres" "suspense" }}
參數
where 函數接受三個或四個參數。OPERATOR 參數是可選的。
- COLLECTION
- (
any) 一個 [頁面集合] 或 [切片] 的 [映射]。
- KEY
- (
string) 要與VALUE比較的頁面或映射值的鍵。對於頁面集合,常見的比較鍵是Section、Type和Params。要與頁面Params映射中的成員比較,請 [鏈接] 子鍵,如下所示:
{{ $result := where .Site.RegularPages "Params.foo" "bar" }}
- OPERATOR
- (
string) 邏輯比較 運算符。 - VALUE
- (
any) 要比較的值。要比較的值必須具有可比較的資料類型。例如:
| 比較 | 結果 |
|---|---|
"123" "eq" "123" |
true |
"123" "eq" 123 |
false |
false "eq" "false" |
false |
false "eq" false |
true |
當其中一個或兩個要比較的值為切片時,請使用 in、not in 或 intersect 運算符,如下所示。
運算符
使用以下任意邏輯運算符:
=,==,eq- (
bool) 報告給定欄位值是否等於VALUE。 !=,<>,ne- (
bool) 報告給定欄位值是否不等於VALUE。 >=,ge- (
bool) 報告給定欄位值是否大於或等於VALUE。 >,gttrue報告給定欄位值是否大於VALUE。<=,le- (
bool) 報告給定欄位值是否小於或等於VALUE。 <,lt- (
bool) 報告給定欄位值是否小於VALUE。 in- (
bool) 報告給定欄位值是否是VALUE的成員。比較字串對切片或字串對字串。請參見 詳細信息。 not in- (
bool) 報告給定欄位值是否不是VALUE的成員。比較字串對切片或字串對字串。請參見 詳細信息。 intersect- (
bool) 報告給定欄位值(切片)是否包含與VALUE共有的元素。請參見 詳細信息。 likeNew in v0.116.0- (
bool) 報告給定欄位值是否符合VALUE中指定的正則表達式。使用like運算符比較string值。當將其他資料類型與正則表達式比較時,like運算符會返回false。
字串比較
比較給定欄位的值與 string:
{{ $pages := where .Site.RegularPages "Section" "eq" "books" }}
{{ $pages := where .Site.RegularPages "Section" "ne" "books" }}
數字比較
{{ $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 }}
布林值比較
比較給定欄位的值與 bool:
{{ $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 }}
成員比較
例如,要返回一個頁面集合,其中 color 頁面參數是 “red” 或 “yellow”:
{{ $fruit := where site.RegularPages "Section" "eq" "fruit" }}
{{ $colors := slice "red" "yellow" }}
{{ $pages := where $fruit "Params.color" "in" $colors }}
要返回一個頁面集合,其中 “color” 頁面參數既不是 “red” 也不是 “yellow”:
{{ $fruit := where site.RegularPages "Section" "eq" "fruit" }}
{{ $colors := slice "red" "yellow" }}
{{ $pages := where $fruit "Params.color" "not in" $colors }}
交集比較
比較 slice 和 slice,返回具有共同值的集合元素。這通常用於比較分類法術語。
例如,要返回一個頁面集合,其中 “genres” 分類法中的任何術語為 “suspense” 或 “romance”:
{{ $books := where site.RegularPages "Section" "eq" "books" }}
{{ $genres := slice "suspense" "romance" }}
{{ $pages := where $books "Params.genres" "intersect" $genres }}
正則表達式比較
New in v0.116.0要返回一個頁面集合,其中 “author” 頁面參數以 “victor” 或 “Victor” 開頭:
{{ $pages := where .Site.RegularPages "Params.author" "like" `(?i)^victor` }}
在指定正則表達式時,請使用原始的 string literal(反引號),而非解釋過的字串字面量(雙引號),以簡化語法。使用解釋過的字串字面量時,您必須對反斜線進行轉義。
Go 的正則表達式套件實現了 [RE2 語法]。RE2 語法是接受的 PCRE 語法的一個子集,粗略來說,並且有各種 caveats。請注意,RE2 不支援 \C 轉義序列。
日期比較
預設日期
有四個預設的 Front Matter 日期:date、publishDate、lastmod 和 expiryDate。無論使用何種 Front Matter 資料格式(TOML、YAML 或 JSON),這些都是 time.Time 類型值,可以進行精確的比較。
例如,返回創建時間早於當前年份的頁面集合:
{{ $startOfYear := time.AsTime (printf "%d-01-01" now.Year) }}
{{ $pages := where .Site.RegularPages "Date" "lt" $startOfYear }}
自訂日期
使用自訂的 front matter 日期時,比較操作會依照 front matter 數據格式(TOML、YAML 或 JSON)來決定。
在 TOML 格式中,日期值是第一類別(first-class)。TOML 擁有日期數據類型,而 JSON 和 YAML 沒有。如果您引用 TOML 日期,它會是字串。如果您不引用 TOML 日期值,它將會是 time.Time 型別,從而可以進行精確的比較。
在下列的 TOML 範例中,請注意事件日期並未被引用。
+++
title = '2024 User Conference'
eventDate = 2024-04-01
+++要返回一組未來的事件:
{{ $events := where .Site.RegularPages "Type" "events" }}
{{ $futureEvents := where $events "Params.eventDate" "gt" now }}
當使用 YAML、JSON 或引用的 TOML 值時,自訂日期會是字串;您無法將它與 time.Time 型別的值進行比較。如果自訂日期格式在不同頁面間一致,則可以進行字串比較。為了保險起見,透過遍歷整個集合來過濾頁面:
{{ $events := where .Site.RegularPages "Type" "events" }}
{{ $futureEvents := slice }}
{{ range $events }}
{{ if gt (time.AsTime .Params.eventDate) now }}
{{ $futureEvents = $futureEvents | append . }}
{{ end }}
{{ end }}
Nil 比較
要返回一組包含 “color” 參數的頁面,並與 nil 比較:
{{ $pages := where .Site.RegularPages "Params.color" "ne" nil }}
要返回一組不包含 “color” 參數的頁面,並與 nil 比較:
{{ $pages := where .Site.RegularPages "Params.color" "eq" nil }}
在上述的範例中,請注意 nil 並未被引用。
嵌套比較
以下兩者等價:
{{ $pages := where .Site.RegularPages "Type" "tutorials" }}
{{ $pages = where $pages "Params.level" "eq" "beginner" }}
{{ $pages := where (where .Site.RegularPages "Type" "tutorials") "Params.level" "eq" "beginner" }}
可攜式區塊比較
對於主題作者來說,可以避免硬編碼區塊名稱,透過在 Site 物件上使用 where 函數與 MainSections 方法來達成。
{{ $pages := where .Site.RegularPages "Section" "in" .Site.MainSections }}
通過這個結構,主題作者可以指示使用者在站點配置中指定主區塊:
params:
mainSections:
- blog
- galleries
[params]
mainSections = ['blog', 'galleries']
{
"params": {
"mainSections": [
"blog",
"galleries"
]
}
}
如果 params.mainSections 在站點配置中未被定義,則 MainSections 方法會返回一個包含單一元素的切片—即包含最多頁面的頂層區塊。
布林值/未定義比較
考慮以下網站內容:
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
前兩個頁面有 “exclude” 欄位,但最後一個頁面並未定義這個欄位。在進行 相等 測試時,第三個頁面將 被排除;進行 不等 測試時,第三個頁面將 被包含。
相等測試
此模板:
<ul>
{{ range where .Site.RegularPages "Params.exclude" "eq" false }}
<li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li>
{{ end }}
</ul>
將渲染為:
<ul>
<li><a href="/posts/post-1/">Post 1</a></li>
</ul>
此模板:
<ul>
{{ range where .Site.RegularPages "Params.exclude" "eq" true }}
<li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li>
{{ end }}
</ul>
將渲染為:
<ul>
<li><a href="/posts/post-2/">Post 2</a></li>
</ul>
不等測試
此模板:
<ul>
{{ range where .Site.RegularPages "Params.exclude" "ne" false }}
<li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li>
{{ end }}
</ul>
將渲染為:
<ul>
<li><a href="/posts/post-2/">Post 2</a></li>
<li><a href="/posts/post-3/">Post 3</a></li>
</ul>
此模板:
<ul>
{{ range where .Site.RegularPages "Params.exclude" "ne" true }}
<li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li>
{{ end }}
</ul>
將渲染為:
<ul>
<li><a href="/posts/post-1/">Post 1</a></li>
<li><a href="/posts/post-3/">Post 3</a></li>
</ul>
排除未定義欄位的頁面,進行布林 不相等 測試:
- 使用布林比較創建集合
- 使用
nil比較創建集合 - 使用
collections.Complement函數將第二個集合從第一個集合中扣除。
範例模板:
{{ $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>
渲染後結果為:
<ul>
<li><a href="/posts/post-1/">Post 1</a></li>
</ul>
範例模板:
{{ $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>
渲染後結果為:
<ul>
<li><a href="/posts/post-1/">Post 2</a></li>
</ul>
這樣的做法是將兩組頁面進行分開:一組具有布林 exclude 欄位,另一組 exclude 欄位未定義,再將未定義欄位的集合從布林比較結果中扣除,以達到想要的過濾邏輯。