Subqueries and nested data
Modern applications often work with complex, nested data structures like arrays of objects or hierarchical JSON. React Query Builder's subquery feature lets you build sophisticated queries against these nested data structures using intuitive match modes like "all," "some," or "none."
Configuring subqueries
To enable subqueries for a field, add a matchModes
property to the field definition. This property controls which match modes are available and how they're labeled.
Match modes configuration
The matchModes
property accepts several formats:
true
- Enables all available match modes with default labelsMatchMode[]
- Array of match mode names (e.g.,['all', 'some', 'none']
)Option<MatchMode>[]
- Array of objects with custom labels (e.g.,[{ name: 'all', label: 'Every' }]
)
const fields: Field[] = [
{
name: 'nestedStringArray',
label: 'Nested String Array',
// Enable all match modes with default labels
matchModes: true,
},
{
name: 'nestedNumberArray',
label: 'Nested Number Array',
// Enable specific match modes with custom labels
matchModes: [
{ name: 'all', label: 'Every' },
{ name: 'none', label: 'Not one' },
{ name: 'some', label: 'Several' },
],
},
{
name: 'nestedObjectArray',
label: 'Nested Object Array',
// Enable specific match modes with default labels
matchModes: ['all', 'none', 'some'],
// Define properties of objects in the nested array
subproperties: [
{ name: 'firstName', label: 'First Name' },
{ name: 'lastName', label: 'Last Name' },
],
},
];
Available match modes
React Query Builder supports six match modes:
Mode | Type | Description | Requires threshold |
---|---|---|---|
all | Unary | Every item in the array matches the subquery | No |
some | Unary | At least one item in the array matches the subquery | No |
none | Unary | No items in the array match the subquery | No |
atLeast | Threshold | At least N items match the subquery | Yes |
atMost | Threshold | At most N items match the subquery | Yes |
exactly | Threshold | Exactly N items match the subquery | Yes |
Working with object properties
For arrays containing objects (not just primitive values), use the subproperties
configuration to define which object properties are available in the subquery. This works exactly like the main fields
prop.
If subproperties
is not defined, the field selector will not be rendered in subquery rules, and the field
property should be left as an empty string.
Query structure
Subqueries are stored in the rule's value
property as a nested RuleGroupType
. The match
property contains the mode and optional threshold:
const exampleQuery: RuleGroupType = {
combinator: 'and',
rules: [
{
field: 'nestedStringArray',
operator: '=', // Ignored when match is present
match: { mode: 'atMost', threshold: 2 },
value: {
combinator: 'and',
rules: [{ field: '', operator: 'contains', value: 'abc' }],
},
},
{
field: 'nestedObjectArray',
operator: '=',
match: { mode: 'all' },
value: {
combinator: 'and',
rules: [
{ field: 'firstName', operator: 'beginsWith', value: 'S' },
{ field: 'lastName', operator: 'doesNotEndWith', value: 's' },
],
},
},
],
};
The operator
property is ignored when a rule has a valid match
property. The match mode determines how the subquery is evaluated.
Export format support
Most export formats support subqueries, some better than others.
Support level | Formats |
---|---|
Full | "jsonlogic"1, "jsonata", "cel", "spel", "natural_language", |
Partial2 | "sql", "parameterized", "drizzle" |
None | "parameterized_named"3, "prisma", "sequelize", "elasticsearch", "ldap" |
In formats that do not support subqueries, rules that have a valid match
property will be treated as invalid and ignored.
Footnotes
-
JsonLogic was the original inspiration for this feature. ↩
-
The SQL-based formats only support nested arrays of primitive values, and only when the
preset
value is "postgresql". This is because other RDBMS platforms either have no support for, or overly complex implementations of, nested tables. ↩ -
PostgreSQL does not support named parameters ↩