Requires CUE v0.11.0 or later

Data sometimes needs to include values for one of several mutually exclusive fields, or combinations of those fields. The built-in function matchN can be used to describe constraints such as “require exactly one of these fields”, or “permit up to two of these fields”.

This guide demonstrates how to use matchN as a field validator to enforce different scenarios where you need to limit the combinations of which fields are allowed.

example.cue
package matchn

// A and B have identical matchN constraints of
// "allow at most two of these named fields".

A: {
	matchN(<=2, [{alpha!: _}, {beta!: _}, {gamma!: _}])
	alpha: "foo"
	beta:  "bar"
}

B: matchN(<=2, [{alpha!: _}, {beta!: _}, {gamma!: _}])
B: {
	alpha: "foo"
	beta:  "bar"
	gamma: "baz"
}
TERMINAL
$ cue vet -c
B: invalid value {alpha:"foo",beta:"bar",gamma:"baz"} (does not satisfy matchN): 3 matched, expected <=2:
    ./example.cue:12:4
    ./example.cue:12:11
    ./example.cue:13:4

All matchN constraints require two parameters:

  • The second parameter is a list of constraints. CUE counts how many of these constraints are able to unify successfully with the field that’s being validated (A and B, in our example).
  • The first parameter is a number constraint. For a field to be valid, this constraint must be able to unify successfully with the count produced when CUE tested the list of constraints.

This flexible logic allows for a wide variety of requirements to be expressed using similar matchN validators. With the list of constraints shown in the examples above, a different number constraint would enforce requirements such as:

  • Require exactly one of these fields: 1
  • Allow up to two of these fields: <=2 (also <3)
  • Require at least one of these fields: >=1 (also >0)
  • Require between two and four of these fields: >=2 & <=4 (also 2 | 3 | 4)
  • Require either one, or three of these fields: 1 | 3
  • Require either less than three, or exactly four, or more than five of these fields: <3 | 4 | >5 (also !=3 & !=5)
  • Disallow exactly two of these fields: !=2 (also <2 | >2)

The different encodings that CUE allows for individual number constraints gives you flexibility – you can choose the form that communicates your intent most clearly, given your specific situation. For example, >=2 & <=4 and 2 | 3 | 4 are equivalent in a matchN number constraint, but you might find one more appropriate than the other.

The function’s parameters can also be resolved via references, which helps avoid the matchN duplication shown in the example CUE above. Learn more in Using the built-in function "matchN" as a field validator