blob: 93c2110b6f88d1286f5bdedd902f207cb29dac3c [file] [edit]
// Copyright 2026 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package examples
import (
"fmt"
"log"
"github.com/google/cel-go/cel"
)
// Example_cel_Collections showcases membership, indexing, search (exists), all, and filter
// on complex collections as documented in https://celbyexample.com/collections/
func Example_cel_Collections() {
orderData := map[string]any{
"id": "ord-123",
"customer": "alice@example.com",
"tags": []string{"express", "gift-wrapped"},
"items": []map[string]any{
{"name": "Laptop", "category": "electronics", "price": 999, "quantity": 1},
{"name": "Cable", "category": "accessories", "price": 29, "quantity": 3},
},
"status": "pending",
}
exprs := []string{
`"express" in order.tags`,
`size(order.tags)`,
`size(order.items)`,
`order.tags[0]`,
`order.items[0].name`,
`order.items[0].price`,
`order.tags.exists(t, t.startsWith("ex"))`,
`order.items.exists(i, i.price > 500)`,
`order.items.exists(i, i.category == "electronics" && i.price > 100)`,
`order.tags.all(t, size(t) > 0)`,
`order.items.all(i, i.quantity > 0)`,
`order.items.all(i, i.price < 10000)`,
`order.tags.filter(t, t != "express")`,
`order.items.filter(i, i.price > 100)[0].name`,
`order.items.filter(i, i.category == "electronics")[0].name`,
}
for _, expr := range exprs {
prg, err := cel.Compile(expr, cel.Variable("order", cel.DynType))
if err != nil {
log.Fatalf("cel.Compile() error for %q: %v", expr, err)
}
out, _, err := prg.Eval(map[string]any{"order": orderData})
if err != nil {
log.Fatalf("prg.Eval() error for %q: %v", expr, err)
}
fmt.Printf("%s -> %v\n", expr, out)
}
// Output:
// "express" in order.tags -> true
// size(order.tags) -> 2
// size(order.items) -> 2
// order.tags[0] -> express
// order.items[0].name -> Laptop
// order.items[0].price -> 999
// order.tags.exists(t, t.startsWith("ex")) -> true
// order.items.exists(i, i.price > 500) -> true
// order.items.exists(i, i.category == "electronics" && i.price > 100) -> true
// order.tags.all(t, size(t) > 0) -> true
// order.items.all(i, i.quantity > 0) -> true
// order.items.all(i, i.price < 10000) -> true
// order.tags.filter(t, t != "express") -> [gift-wrapped]
// order.items.filter(i, i.price > 100)[0].name -> Laptop
// order.items.filter(i, i.category == "electronics")[0].name -> Laptop
}
// Example_cel_Lists showcases list literals, indexing, membership, concatenation, and equality
// as documented in https://celbyexample.com/lists/
func Example_cel_Lists() {
exprs := []string{
`[1, 2, 3]`,
`[]`,
`[1, "two", true]`,
`[[1, 2], [3, 4]]`,
`size([1, 2, 3])`,
`[1, 2, 3].size()`,
`["a", "b", "c"][0]`,
`["a", "b", "c"][2]`,
`[[1, 2], [3, 4]][0][1]`,
`2 in [1, 2, 3]`,
`5 in [1, 2, 3]`,
`[1, 2] + [3, 4]`,
`[1, 2, 3] == [1, 2, 3]`,
`[1, 2, 3] == [3, 2, 1]`,
}
for _, expr := range exprs {
prg, err := cel.Compile(expr)
if err != nil {
log.Fatalf("cel.Compile() error for %q: %v", expr, err)
}
out, _, err := prg.Eval(cel.NoVars())
if err != nil {
log.Fatalf("prg.Eval() error for %q: %v", expr, err)
}
fmt.Printf("%s -> %v\n", expr, out)
}
// Output:
// [1, 2, 3] -> [1, 2, 3]
// [] -> []
// [1, "two", true] -> [1, two, true]
// [[1, 2], [3, 4]] -> [[1, 2], [3, 4]]
// size([1, 2, 3]) -> 3
// [1, 2, 3].size() -> 3
// ["a", "b", "c"][0] -> a
// ["a", "b", "c"][2] -> c
// [[1, 2], [3, 4]][0][1] -> 2
// 2 in [1, 2, 3] -> true
// 5 in [1, 2, 3] -> false
// [1, 2] + [3, 4] -> [1, 2, 3, 4]
// [1, 2, 3] == [1, 2, 3] -> true
// [1, 2, 3] == [3, 2, 1] -> false
}
// Example_cel_Maps showcases map literals, size, field/key access, membership, and comparison
// as documented in https://celbyexample.com/maps/
func Example_cel_Maps() {
exprs := []string{
`{"a": 1, "b": 2}.a`,
`size({"a": 1, "b": 2})`,
`{1: "one", 2: "two"}[1]`,
`{"nested": {"a": 1}}.nested.a`,
`size({"a": 1, "b": 2, "c": 3})`,
`{"a": 1, "b": 2}.size()`,
`{"a": 1, "b": 2}["a"]`,
`{"a": 1, "b": 2}.a`,
`"a" in {"a": 1, "b": 2}`,
`"c" in {"a": 1, "b": 2}`,
`{"a": 1, "b": 2} == {"a": 1, "b": 2}`,
`{"a": 1} == {"a": 2}`,
}
for _, expr := range exprs {
prg, err := cel.Compile(expr)
if err != nil {
log.Fatalf("cel.Compile() error for %q: %v", expr, err)
}
out, _, err := prg.Eval(cel.NoVars())
if err != nil {
log.Fatalf("prg.Eval() error for %q: %v", expr, err)
}
fmt.Printf("%s -> %v\n", expr, out)
}
// Output:
// {"a": 1, "b": 2}.a -> 1
// size({"a": 1, "b": 2}) -> 2
// {1: "one", 2: "two"}[1] -> one
// {"nested": {"a": 1}}.nested.a -> 1
// size({"a": 1, "b": 2, "c": 3}) -> 3
// {"a": 1, "b": 2}.size() -> 2
// {"a": 1, "b": 2}["a"] -> 1
// {"a": 1, "b": 2}.a -> 1
// "a" in {"a": 1, "b": 2} -> true
// "c" in {"a": 1, "b": 2} -> false
// {"a": 1, "b": 2} == {"a": 1, "b": 2} -> true
// {"a": 1} == {"a": 2} -> false
}