Picking the first value you find from 2 objects in Rego
Monday, September 30, 2019
This post is about "how you can pick the first value you find from 2 objects" in Rego, a query language used in OPA (Open Policy Agent).
This use case is a little confusing and you'll probably think "When is this necessary?". One example is shared in "Merge Objects" in the official docs.
When merging multiple objects, you'll definitely need to think about colliding keys and how to decide which
key
,
value
to choose. This is where you'll want to use "Pick the first value you find from 2 objects".
Let's dive into details.
Logical OR in Rego
The function which "Picks the first value it finds from 2 objects" will be called
pick_first
. Here's how the implementation will look like.
has_key(x, k) {
_ := x[k]
}
pick_first(k, a, b) = a[k]
pick_first(k, a, b) = b[k] { not has_key(a, k) }
See how there are 2 definitions of
pick_first(k, a, b)
. This is how you express a Logical OR in Rego. So the expression above is like saying:
"For key
k
, choose the value from object
a
, OR, choose the value from object
b
if object
a
DOES NOT HAVE key
k
."
If you feel uncomfortable with the
has_key
function, look at my previous post specifically explaining about it here:
Example
Here's a complete example demonstrating the usage of
pick_first
.
has_key(x, k) {
_ := x[k]
}
pick_first(k, a, b) = a[k]
pick_first(k, a, b) = b[k] { not has_key(a, k) }
x := {"a": true, "b": false}
y := {"b": "foo", "c": 4}
first_values = fv {
a := pick_first("a", x, y)
b := pick_first("b", x, y)
c := pick_first("c", x, y)
fv := {
"a": a,
"b": b,
"c": c
}
}
If you evaluate
first_values
, the result would be:
{
"a": true,
"b": false,
"c": 4
}
Notice how key
false
was chosen from object
x
's key
b
. The only time the values of object
y
are selected are when the key doesn't exist in object
x
(e.g. key
c
).
You can check this out for yourself in the following playground:
https://play.openpolicyagent.org/p/puwMTreKjD