More operators
This document explains some of the operators available in Content Advanced Search, including: queryString, compound, regexp, exists, nested, and language. Additional operators are detailed in a separate document, titled "Operators"
queryString operator
queryString operatorDescription
The queryString operator allows you to write complex search queries in a compact string format. It supports field-specific searches, Boolean operators (AND, OR, NOT), wildcards, and grouping with parentheses.
This operator is recommended for user-submitted searches, particularly for advanced users who want to create intricate search conditions using the query syntax. It provides a powerful and flexible way to search across multiple fields with complex Boolean logic.
Syntax
{
"queryString": {
"query": "(<field-to-search>: (<search-values>) AND|OR (<search-values>)) AND|OR (<search-values>)",
"defaultPath": "<field-to-search>",
"score": <score-options>
}
}Options
| Field | Type | Description | Required? |
|---|---|---|---|
query | string | The query string. | Yes |
defaultPath | string | The default field to search if no field is specified in the query. | No |
defaultOperator | string | Default boolean operator for terms without explicit operators: "AND" (all terms required) or "OR" (any term). Default: "AND". | No |
score | object | Score modification options. See Score modification . | No |
Query syntax
The queryString operator searches one or more fields using colon-delimited field-value pairs. For example, to search the heroMedia.title field for "championship", use heroMedia.title:championship.
Combining search criteria
Combine multiple fields and values using the following operators:
| Operator | Description | Example |
|---|---|---|
AND | Boolean AND. All search values must be present for a document to be included in results. | heroMedia.title:team AND pinned:true |
OR | Boolean OR. At least one search value must be present for a document to be included in results. | tags:breaking OR tags:exclusive |
NOT | Boolean NOT. Specified search value must be absent for a document to be included in results. | pinned:true NOT tags:draft |
- | Alternative NOT syntax. Excludes documents matching the value. | pinned:true -tags:draft |
TO | Range operator. Use [] for inclusive, {} for exclusive, or {] and [} for half-open ranges. | publishDate:[2024-01-01 TO 2024-12-31] |
() | Grouping. Use parentheses to group fields and values into subqueries. | (heroMedia.title:team OR heroMedia.title:club) AND pinned:true |
Wildcards
Run wildcard queries using the following:
| Operator | Description | Example |
|---|---|---|
? | Matches any single character. | te?m matches "team" or "term" |
* | Matches zero or more characters. | team* matches "team", "teams", "teammate" |
Important: The queryString operator does not support wildcard queries with * as the first character. Any characters preceding the * are treated as a prefix that must be matched exactly.
Phrases
Use double quotes to search for exact phrases:
| Syntax | Description | Example |
|---|---|---|
"..." | Exact phrase match with words in order. | "team a fc" matches exactly |
Examples
Field-specific search:
heroMedia.title:championship- Search for "championship" in the title field
Combined searches:
tags:breaking AND publishDate:[now-7d TO now]- Articles tagged "breaking" published in last 7 days
Grouping with boolean logic:
(team OR club) AND final- Articles containing ("team" OR "club") AND "final"
Range queries:
publishDate:[2024-01-01 TO 2024-12-31]- Inclusive date rangereadTimeMinutes:{5 TO *}- More than 5 minutes read time (exclusive lower bound)
Wildcards:
team*- Matches "team", "teams", "teammate"te?m- Matches "team", "term"
Phrases:
heroMedia.title:"team a fc"- Exact phrase in title field
Examples
Basic field search
Search for "championship" in the title field:
{
"query": {
"queryString": {
"query": "heroMedia.title:championship"
}
}
}Multiple fields with Boolean logic
Search for articles about "team a" in title or content, published in the last 7 days:
{
"query": {
"queryString": {
"query": "(heroMedia.title:\"team a\" OR content.text:\"team a\") AND publishDate:[now-7d TO now]"
}
}
}Using default field
Search for "breaking news" in the default field (tags):
{
"query": {
"queryString": {
"query": "breaking news",
"defaultPath": "tags"
}
}
}Complex query with wildcards and grouping
{
"query": {
"queryString": {
"query": "(heroMedia.title:champion* OR heroMedia.title:final*) AND tags:sport* AND NOT tags:draft"
}
}
}Using defaultOperator
defaultOperatorThe defaultOperator controls how terms are combined when no explicit boolean operator is specified.
Default behaviour (AND):
{
"query": {
"queryString": {
"query": "team championship",
"defaultPath": "heroMedia.title"
}
}
}This requires both "team" AND "championship" to be present (default behaviour).
Using OR as default operator:
{
"query": {
"queryString": {
"query": "team championship",
"defaultPath": "heroMedia.title",
"defaultOperator": "OR"
}
}
}This matches articles with "team" OR "championship" (or both).
Important: The defaultOperator only affects terms without explicit operators. Terms connected with explicit AND/OR operators always respect those operators:
{
"query": {
"queryString": {
"query": "team championship AND final",
"defaultOperator": "OR"
}
}
}This evaluates as: (team OR championship) AND final
- "team" and "championship" are combined with OR (defaultOperator)
- "final" is required (explicit AND operator)
Best practices
Never embed user input directly in query strings
Bad - User input embedded in query string:
{
"queryString": {
"query": "categories.id:a1b2c3d4 AND " + userInput
}
}This causes problems because user input can interfere with your base query logic.
Examples of query interference:
If a user enters: heroMedia.title:championship OR categories.id:b2c3d4e5
The resulting query becomes:
categories.id:a1b2c3d4 AND heroMedia.title:championship OR categories.id:b2c3d4e5
Due to operator precedence, this effectively becomes:
(categories.id:a1b2c3d4 AND heroMedia.title:championship) OR categories.id:b2c3d4e5
Now your categories.id:a1b2c3d4 filter is bypassed, and results from b2c3d4e5 are included.
Other problematic inputs:
- User enters
heroMedia.title:foo) OR (categories.id:c3d4e5f6- breaks out of boolean grouping - User enters
NOT categories.id:a1b2c3d4- inverts your filter logic - User enters special characters or malformed syntax - causes query parsing errors
Good - User input isolated:
{
"compound": {
"must": [
<user-submitted-query>
],
"filter": [
{
"queryString": {
"query": "categories.id:a1b2c3d4"
}
}
]
}
}Operator precedence
Boolean operators are evaluated with the following precedence (highest to lowest):
- Parentheses
()- Highest precedence, evaluated first - NOT /
-- Negation - AND - Conjunction (higher than OR)
- OR - Disjunction (lowest precedence)
Example:
categories.id:a1b2c3d4 AND heroMedia.title:championship OR categories.id:b2c3d4e5
Is evaluated as:
(categories.id:a1b2c3d4 AND heroMedia.title:championship) OR categories.id:b2c3d4e5
Why this matters:
Without understanding precedence, the query above might unexpectedly include other category results. To ensure both conditions are required, use explicit parentheses:
categories.id:a1b2c3d4 AND (heroMedia.title:championship OR categories.id:b2c3d4e5)
Best practice: Always use parentheses to make boolean logic explicit and avoid relying on operator precedence.
Notes
- This operator does not support boosting syntax (e.g.,
heroMedia.title:championship^2) - Special characters in query strings must be escaped:
+ - = && || > < ! ( ) { } [ ] ^ " ~ * ? : \ / - Invalid query syntax will result in a search error
- Wildcard queries can be slow on large datasets
- This operator searches analysed text fields, so searches are case-insensitive and apply text analysis
- Wildcard support: The
queryStringoperator supports wildcards (*and?) within field values in the query string itself (e.g.,heroMedia.title:champ*). ThedefaultPathparameter does NOT support wildcards - you must specify an exact field name - The default
defaultOperatoris"AND", requiring all terms without explicit operators to be present - The
defaultOperatoronly affects implicit term combinations; explicit AND/OR operators in the query string always take precedence
compound operator
compound operatorDescription
The compound operator combines multiple query clauses using Boolean logic to create complex search queries. It allows you to specify which conditions must match, should match, or must not match, giving you fine-grained control over search results.
Use this operator when:
- Combining multiple search criteria
- Creating complex filtering logic
- Requiring some conditions whilst making others optional
- Excluding specific content from results
- Influencing scoring through must/should clauses
Syntax
{
"compound": {
"must": [<query>, ...],
"should": [<query>, ...],
"mustNot": [<query>, ...],
"filter": [<query>, ...],
"minimumShouldMatch": <number>,
"score": <score-options>
}
}Options
| Field | Type | Description | Required? |
|---|---|---|---|
must | array | Array of queries that must all match. Contributes to scoring. | Conditional |
should | array | Array of queries where at least one should match. Contributes to scoring. | Conditional |
mustNot | array | Array of queries that must not match. Does not contribute to scoring. | Conditional |
filter | array | Array of queries that must match but do not contribute to scoring (for filtering only). | Conditional |
minimumShouldMatch | number | Minimum number of should clauses that must match. Default is 1 if no must or filter present, otherwise 0. | No |
score | object | Score modification options. See Score. | No |
Clause Behaviour
| Clause | Matching Requirement | Affects Score? |
|---|---|---|
must | All queries in this array must match | Yes |
should | At least one query should match if no must or filter clauses are present. When combined with must or filter, becomes optional but boosts score of matching documents | Yes |
mustNot | None of these queries should match. Used to exclude articles | No |
filter | All queries must match, but does not affect scoring. Use for exact filtering | No |
Note: At least one of must, should, mustNot, or filter must be specified.
Examples
Must and should combination
Find articles about "team a" that should also mention "trophy" and are in the "5a3c1e8b-4f2d-4a1c-9b8e-1234567890ab" category:
{
"query": {
"compound": {
"must": [
{
"text": {
"query": "team a",
"path": "heroMedia.title"
}
}
],
"should": [
{
"text": {
"query": "trophy",
"path": "content.text"
}
}
],
"filter": [
{
"equal": {
"path": "categories.id",
"value": "5a3c1e8b-4f2d-4a1c-9b8e-1234567890ab"
}
}
]
}
}
}Note: Filtering by keyword fields like categories.id should be done using the filter clause for better performance.
Exclude specific tags
Find articles excluding platform-related tags:
{
"query": {
"compound": {
"mustNot": [
{
"in": {
"path": "tags",
"values": ["app-only", "maintenance"]
}
}
]
}
}
}Filter by date range without affecting score
Find recent articles about "transfers" published in the last 30 days:
{
"query": {
"compound": {
"must": [
{
"text": {
"query": "transfers",
"path": ["heroMedia.title", "content.text"]
}
}
],
"filter": [
{
"range": {
"path": "publishDate",
"gte": "now-30d"
}
}
]
}
}
}Complex multi-criteria search
Find articles that:
- Filter by pinned
- Filtered by specific category
- Should mention "final" or "cup" in the title
- Must not have certain tags
{
"query": {
"compound": {
"should": [
{
"text": {
"query": "final",
"path": "heroMedia.title"
}
},
{
"text": {
"query": "cup",
"path": "heroMedia.title"
}
}
],
"mustNot": [
{
"in": {
"path": "tags",
"values": ["app-only", "maintenance"]
}
}
],
"filter": [
{
"equal": {
"path": "pinned",
"value": true
}
},
{
"equal": {
"path": "categories.id",
"value": "5a3c1e8b-4f2d-4a1c-9b8e-1234567890ab"
}
}
]
}
}
}Tag-based filtering
Find articles with specific tags, excluding certain tags:
{
"query": {
"compound": {
"mustNot": [
{
"equal": {
"path": "tags",
"value": "app-only"
}
}
],
"filter": [
{
"in": {
"path": "tags",
"values": ["breaking-news", "exclusive"]
}
}
]
}
}
}Nested compound queries
Combine compound queries for even more complex logic that:
- Must match either "team a" in "5a3c1e8b-4f2d-4a1c-9b8e-1234567890ab"
- Or "team b" in "7b4d2f9c-5e3a-4b2d-8c9f-2345678901bc"
{
"query": {
"compound": {
"should": [
{
"compound": {
"must": [
{
"text": {
"query": "team a",
"path": "heroMedia.title"
}
}
],
"filter": [
{
"equal": {
"path": "categories.id",
"value": "5a3c1e8b-4f2d-4a1c-9b8e-1234567890ab"
}
}
]
}
},
{
"compound": {
"must": [
{
"text": {
"query": "team b",
"path": "heroMedia.title"
}
}
],
"filter": [
{
"equal": {
"path": "categories.id",
"value": "7b4d2f9c-5e3a-4b2d-8c9f-2345678901bc"
}
}
]
}
}
]
}
}
}Per-field boosting
Find articles about "championship" that should also mention "winner" or "runner-up" to boost their relevance:
{
"query": {
"compound": {
"must": [
{
"text": {
"query": "championship",
"path": ["heroMedia.title", "content.text"]
}
}
],
"should": [
{
"text": {
"query": "winner",
"path": ["heroMedia.title", "content.text"],
"score": {
"boost": {
"value": 10.0
}
}
}
},
{
"text": {
"query": "runner-up",
"path": ["heroMedia.title", "content.text"],
"score": {
"boost": {
"value": 5.0
}
}
}
}
]
}
}
}Minimum should match
Find articles that should mention at least two of the following: "breaking news", "title", or published in the last 24 hours, while filtering by specific categories:
{
"query": {
"compound": {
"should": [
{
"equal": {
"path": "pinned",
"value": true
}
},
{
"text": {
"query": "breaking news",
"path": "heroMedia.title"
}
},
{
"range": {
"path": "publishDate",
"gte": "now-24h"
}
}
],
"filter": [
{
"in": {
"path": "categories.id",
"values": [
"5a3c1e8b-4f2d-4a1c-9b8e-1234567890ab",
"7b4d2f9c-5e3a-4b2d-8c9f-2345678901bc"
]
}
}
],
"minimumShouldMatch": 2
}
}
}This requires at least 50% of the should clauses (2 out of 4) to match.
Clause interaction reference
The following table clarifies how must, should, filter, and mustNot interact:
| Clause Present | Must Match? | Affects Score? | Use Case |
|---|---|---|---|
must only | All must clauses | Yes | Required conditions that affect relevance |
should only | At least 1 (or minimumShouldMatch) | Yes | Optional conditions, any can match |
filter only | All filter clauses | No | Required conditions, no scoring needed |
mustNot only | None can match | No | Exclusion only |
must + should | All must + 0+ should (optional) | Yes | Required + optional boost |
filter + should | All filter + 0+ should (optional) | Yes (should only) | Required filter + optional boost |
must + filter | All must + all filter | Yes (must only) | Required scoring + required filtering |
must + mustNot | All must + none mustNot | Yes (must only) | Include + exclude with scoring |
Any + mustNot | (depends) + none mustNot | (depends) | Any pattern + exclusions |
Key insights:
shouldclauses are required when alone, optional when combined withmustorfilterfilternever affects scoring, even when combined with other clausesmustNotnever affects scoring (pure exclusion)- Use
minimumShouldMatchto require multipleshouldclauses (default is 1 when alone, 0 when withmust/filter)
Notes
- Use
filterinstead ofmustwhen you don't need scoring (better performance) shouldclauses only affect scoring when combined withmustorfiltermustNotis useful for excluding irrelevant content by tags or categories- Compound queries can be nested for complex boolean logic
- Keep queries simple when possible for better performance
shouldclauses can include scoring boosts to influence relevance- Use
minimumShouldMatchto require multiple optional conditions whilst maintaining flexibility
regexp operator
regexp operatorDescription
The regexp operator finds articles where a field value matches a specified regular expression pattern. This provides powerful pattern matching capabilities for complex search requirements where simple text matching isn't sufficient.
Use this operator when:
- Searching for values that match a specific pattern (e.g., article codes, IDs)
- Finding values with specific character sequences or formats
- Implementing advanced text matching with wildcards and alternation
Syntax
{
"regexp": {
"query": "<regex-pattern>",
"path": "<field-to-search>",
"score": <score-options>
}
}Options
| Field | Type | Description | Required? |
|---|---|---|---|
query | string | The regular expression pattern to match. | Yes |
path | string | The field to search. See Query path. | Yes |
score | object | Score modification options. See Score modification . | No |
Examples
Basic pattern matching
Find articles with tags matching a specific pattern:
{
"query": {
"regexp": {
"query": "foot.*",
"path": "tags"
}
}
}This will match:
- "football"
- "footgolf"
- "foot-racing"
Matches: "art-1234", "art-5678", etc.
Alternation
Find articles from multiple specific providers:
{
"query": {
"regexp": {
"query": "(web|mobile|tablet)-.*",
"path": "content.platforms"
}
}
}Matches: "web-app", "mobile-native", "tablet-responsive", etc.
Character classes
Find tags with specific character patterns:
{
"query": {
"regexp": {
"query": "[a-z]+-[0-9]+",
"path": "tags"
}
}
}Matches: "team-123", "player-456", etc.
Case-insensitive matching
Find slugs with optional prefixes:
{
"query": {
"regexp": {
"query": "(article|story)-.*",
"path": "slug"
}
}
}Matches: "article-2024-final", "story-breaking-news", etc.
Search with score boost
Boost articles with specific ID patterns:
{
"query": {
"regexp": {
"query": "breaking-.*",
"path": "tags",
"score": {
"boost": {
"value": 2.5
}
}
}
}
}Nested field pattern matching
Find articles with linked IDs matching a pattern:
{
"query": {
"nested": {
"path": "linkedIds",
"query": {
"regexp": {
"query": "t[0-9]{3,}",
"path": "linkedIds.sourceSystemId"
}
}
}
}
}Matches nested IDs: "t123", "t4567", etc.
Complex pattern with score modification
Find articles with specific category slug patterns and apply a constant score:
{
"query": {
"nested": {
"path": "categories",
"query": {
"regexp": {
"query": "division-(one|two|three)",
"path": "categories.id",
"score": {
"constant": {
"value": 5.0
}
}
}
}
}
}
}Leading Wildcards
Leading wildcards (patterns starting with .* or .+) are not supported because they require scanning every term in the index, which can cause severe performance degradation.
Instead of:
{
"regexp": {
"query": ".*-sport",
"path": "tags"
}
}Consider alternative approaches:
- If searching for a suffix, restructure your data to support prefix searches
- Use compound queries with multiple specific patterns
- Use the
textoperator for general word matching
Regex Syntax
The following regex syntax is supported:
| Pattern | Description |
|---|---|
. | Any character |
* | Zero or more of the preceding element |
+ | One or more of the preceding element |
? | Zero or one of the preceding element |
[abc] | Character class (matches a, b, or c) |
[a-z] | Character range (matches a through z) |
[^abc] | Negated character class |
(abc) | Grouping |
a||b | Alternation (matches a or b) |
{n} | Exactly n occurrences |
{n,} | n or more occurrences |
{n,m} | Between n and m occurrences |
Note: The search engine uses a specific regular expression syntax that may differ from other regex implementations. Some advanced features (like lookahead or lookbehind) are not supported.
exists operator
exists operatorDescription
The exists operator finds articles where a specified field exists and has a non-null value. This is useful for filtering content based on the presence or absence of specific fields.
Use this operator when:
- Finding articles that have a specific field populated
- Filtering out articles missing certain data
- Checking if optional fields are present
Syntax
{
"exists": {
"path": "<field-to-check>",
"score": <score-options>
}
}Options
| Field | Type | Description | Required? |
|---|---|---|---|
path | string | The field to check for existence. See Query Path. | Yes |
score | object | Score modification options. See Score. | No |
What counts as "exists"
A field is considered to exist if:
- The field is present and has a value
- The field is an empty string
"" - Arrays containing at least one null or non-null value, such as
[null, "foo"]
A field does NOT exist if:
- The field is not present in the article
- The field is explicitly set to
null - The field is an empty array
[]
Examples
Check if field exists
Find articles that have hero media:
{
"query": {
"exists": {
"path": "heroMedia"
}
}
}Check nested fields
Find articles that have author information:
{
"query": {
"exists": {
"path": "author.name"
}
}
}Combined with mustNot to find missing fields
mustNot to find missing fieldsFind articles that don't have text content:
{
"query": {
"compound": {
"mustNot": [
{
"exists": {
"path": "content.text"
}
}
]
}
}
}Find articles with tags
Find all articles that have at least one tag:
{
"query": {
"exists": {
"path": "tags"
}
}
}Find articles with linked data
Find articles that have linked player or team data:
{
"query": {
"exists": {
"path": "linkedIds"
}
}
}Multiple field or wildcard matching
Find articles with tags or any category field:
{
"query": {
"exists": {
"path": ["tags", "categories.*"]
}
}
}Notes
- Empty strings are considered as "exists"
nullvalues and empty arrays are considered as "does not exist"- Useful in combination with
compoundqueries to include or exclude articles based on field presence - Can be used to validate data completeness across your content
- Checking nested fields (e.g.,
author.name) only verifies that the nested path exists
nested operator
nested operatorDescription
The nested operator queries nested objects within articles. Nested objects are commonly used to store structured data like categories, or linked entities where each item has multiple related fields that need to be queried together.
Use this operator when:
- Querying arrays of objects where field relationships matter
- Working with structured nested data
- Need to match multiple fields within the same nested object
- Ensuring query conditions apply to a single nested object, not across the array
Syntax
{
"nested": {
"path": "<nested-field-path>",
"query": <query-operator>,
"score": <score-options>
}
}Options
| Field | Type | Description | Required? |
|---|---|---|---|
path | string | The path to the nested field. | Yes |
query | object | The query to apply to nested objects. Can be any Content Advanced Search operator. | Yes |
score | object | Score modification options. See Score modification. | No |
When to use nested vs regular queries
Regular arrays (use standard operators)
If you have a simple array of values:
{
"tags": ["football", "premier-league", "breaking-news"]
}Use: equal, in, etc.
Nested objects (use nested operator)
If you have an array of objects with multiple fields:
{
"linkedIds": [
{ "sourceSystem": "OPTA_FOOTBALL_TEAM", "sourceSystemId": "t123" },
{ "sourceSystem": "OPTA_FOOTBALL_TEAM", "sourceSystemId": "t456" }
]
}Use: nested operator
When is the nested wrapper required?
nested wrapper required?Required when:
- Querying multiple fields within the same nested object where field relationships must be preserved
- You need to ensure all conditions match on a single nested object rather than across the array
Optional (provides no benefit) when:
- Querying only a single field within a nested object (e.g., just
categories.id) - The query will work correctly either way
Example: Single field (nested optional):
These queries are functionally identical:
// Without nested wrapper
{
"equal": {
"path": "categories.id",
"value": "5a3c1e8b-4f2d-4a1c-9b8e-1234567890ab"
}
}
// With nested wrapper (no additional benefit)
{
"nested": {
"path": "categories",
"query": {
"equal": {
"path": "categories.id",
"value": "5a3c1e8b-4f2d-4a1c-9b8e-1234567890ab"
}
}
}
}Example: Multiple fields (nested required):
// Correct - ensures both conditions match same object
{
"nested": {
"path": "linkedIds",
"query": {
"compound": {
"must": [
{
"equal": {
"path": "linkedIds.sourceSystem",
"value": "OPTA_FOOTBALL_TEAM"
}
},
{
"equal": {
"path": "linkedIds.sourceSystemId",
"value": "t123"
}
}
]
}
}
}
}Why nested matters
nested mattersGiven the article:
{
"linkedIds": [
{ "sourceSystem": "OPTA_FOOTBALL_TEAM", "sourceSystemId": "123" },
{ "sourceSystem": "OPTA_FOOTBALL_PLAYER", "sourceSystemId": "456" }
]
}Querying for articles with sourceSystem "OPTA_FOOTBALL_TEAM" and sourceSystemId "456":
Without nested (incorrect - would match above article):
{
"compound": {
"must": [
{
"equal": {
"path": "linkedIds.sourceSystem",
"value": "OPTA_FOOTBALL_TEAM"
}
},
{
"equal": {
"path": "linkedIds.sourceSystemId",
"value": "456"
}
}
]
}
}This matches because "OPTA_FOOTBALL_TEAM" exists AND "456" exists (even though they're in different objects).
With nested (correct - would not match):
{
"nested": {
"path": "linkedIds",
"query": {
"compound": {
"must": [
{
"equal": {
"path": "linkedIds.sourceSystem",
"value": "OPTA_FOOTBALL_TEAM"
}
},
{
"equal": {
"path": "linkedIds.sourceSystemId",
"value": "456"
}
}
]
}
}
}
}This only matches if "OPTA_FOOTBALL_TEAM" AND "456" are in the SAME nested object.
Examples
Query nested linked entities
Find articles linked to a specific OPTA team:
{
"query": {
"nested": {
"path": "linkedIds",
"query": {
"compound": {
"filter": [
{
"equal": {
"path": "linkedIds.sourceSystem",
"value": "OPTA_FOOTBALL_TEAM"
}
},
{
"equal": {
"path": "linkedIds.sourceSystemId",
"value": "t123"
}
}
]
}
}
}
}
}Without nested, this could incorrectly match an article where OPTA exists and ANY sourceSystemId matches.
Query specific source system
Find articles with any OPTA linked entities:
{
"query": {
"nested": {
"path": "linkedIds",
"query": {
"equal": {
"path": "linkedIds.sourceSystem",
"value": "OPTA_FOOTBALL_TEAM"
}
}
}
}
}Query multiple linked entities
Find articles linked to multiple specific OPTA entities:
{
"query": {
"nested": {
"path": "linkedIds",
"query": {
"compound": {
"filter": [
{
"equal": {
"path": "linkedIds.sourceSystem",
"value": "OPTA_FOOTBALL_TEAM"
}
},
{
"in": {
"path": "linkedIds.sourceSystemId",
"values": ["t123", "p456", "c789"]
}
}
]
}
}
}
}
}Combine nested with other queries
Find recent articles linked to a specific OPTA entity:
{
"query": {
"compound": {
"filter": [
{
"nested": {
"path": "linkedIds",
"query": {
"compound": {
"filter": [
{
"equal": {
"path": "linkedIds.sourceSystem",
"value": "OPTA_FOOTBALL_TEAM"
}
},
{
"equal": {
"path": "linkedIds.sourceSystemId",
"value": "t100"
}
}
]
}
}
}
},
{
"range": {
"path": "publishDate",
"gte": "now-7d"
}
}
]
}
}
}Query content-level linked entities
Find articles with specific content by source system:
{
"query": {
"compound": {
"filter": [
{
"equal": {
"path": "content.sourceSystem",
"value": "OPTA_FOOTBALL_TEAM"
}
},
{
"equal": {
"path": "content.sourceSystemId",
"value": "p12345"
}
}
]
}
}
}With score boost
Boost articles linked to high-priority entities:
{
"query": {
"nested": {
"path": "linkedIds",
"query": {
"compound": {
"must": [
{
"equal": {
"path": "linkedIds.sourceSystem",
"value": "OPTA_FOOTBALL_TEAM"
}
},
{
"equal": {
"path": "linkedIds.sourceSystemId",
"value": "t100"
}
}
]
}
},
"score": {
"boost": {
"value": 2.0
}
}
}
}
}Scoring and multiple matches
When multiple nested objects match:
If an article has multiple nested objects that match the query, the article is returned once with a relevance score. The score is calculated based on the best-matching nested object, not a sum of all matches.
Example:
// Article with multiple linkedIds
{
"linkedIds": [
{ "sourceSystem": "OPTA_FOOTBALL_TEAM", "sourceSystemId": "t123" },
{ "sourceSystem": "OPTA_FOOTBALL_TEAM", "sourceSystemId": "t456" }
]
}
// Query matching both objects
{
"nested": {
"path": "linkedIds",
"query": {
"equal": {
"path": "linkedIds.sourceSystem",
"value": "OPTA_FOOTBALL_TEAM"
}
}
}
}This article matches (both objects satisfy the condition) and is returned once. The score is based on the best-matching nested document.
Notes
- The
nestedoperator ensures all query conditions apply to the same nested object - Field paths within nested queries include the full path (e.g.,
linkedIds.sourceSystem) - Nested queries can contain any search operator (text, equals, range, compound, etc.)
- Without using
nested, array queries match across all array elements independently - Nested fields must be properly mapped as nested type in the backend index
- When multiple nested objects match, the article is returned once with scoring based on the best match
language operator
language operatorThe language operator filters articles by language with optional fallback languages. This is essential for multi-lingual websites where content may not be available in all languages.
When fallback languages are specified, the operator:
- Attempts to match the primary language first
- Falls back to the first fallback language if the primary is unavailable
- Continues through the fallback list in order
- If none match, behaviour is determined by the
defaultflag:- If
defaultistrue, articles in their source language are returned - If
defaultisfalseor omitted, no results are returned
- If
Syntax
{
"language": {
"primary": "<language-code>",
"fallback": ["<language-code>", ...],
"default": <boolean>
},
"query": {
// your search query
}
}Options
| Field | Type | Description | Required? |
|---|---|---|---|
primary | string | Primary language code (ISO 639-1 two-letter or BCP 47 locale, e.g., en, es, fr-ca) | Yes |
fallback | array | Ordered list of fallback language codes (two-letter or BCP 47 locale). Priority determined by list order. | No |
default | boolean | When true, returns articles in their source language if primary and fallback don't match. When false, returns nothing if no match. Default: false. | No |
Supported language codes
- Two-letter codes (ISO 639-1):
en,fr,es,de,it, etc. - Locale codes (BCP 47):
en-us,fr-ca,es-mx,pt-br, etc.
Both formats can be mixed in the same query.
Examples
Basic language filter (no fallback)
Return only English articles:
{
"language": {
"primary": "en"
},
"query": {
"text": {
"query": "championship",
"path": "heroMedia.title"
}
}
}Language with single fallback
Return English articles, falling back to Spanish if English unavailable:
{
"language": {
"primary": "en",
"fallback": ["es"]
},
"query": {
"text": {
"query": "championship",
"path": "heroMedia.title"
}
}
}Language with multiple fallbacks
Return articles in order of preference: English → Spanish → German → French:
{
"language": {
"primary": "en",
"fallback": ["es", "de", "fr"]
},
"query": {
"text": {
"query": "championship",
"path": "heroMedia.title"
}
}
}Result: Returns English translation if available. If not, tries Spanish, then German, then French. If none match, returns no results.
Using locale codes
Return Canadian French with fallback to France French, then English:
{
"language": {
"primary": "fr-ca",
"fallback": ["fr-fr", "en"]
},
"query": {
"text": {
"query": "hockey",
"path": "heroMedia.title"
}
}
}Result: Returns Canadian French if available. If not, tries France French, then English. If none match, returns no results.
Language filter with complex search
Combine language filtering with compound search queries:
{
"language": {
"primary": "de",
"fallback": ["en"]
},
"query": {
"compound": {
"must": [
{
"text": {
"query": "football",
"path": "heroMedia.title"
}
}
],
"filter": [
{
"range": {
"path": "publishDate",
"gte": "now-7d"
}
}
]
}
},
"page": 1,
"size": 20
}Language with sorting
{
"language": {
"primary": "fr",
"fallback": ["en", "es"]
},
"query": {
"equal": {
"path": "pinned",
"value": true
}
},
"sort": [
{
"field": "publishDate",
"order": "desc"
}
]
}Match all articles in a language
Return all articles in Italian with English fallback:
{
"language": {
"primary": "it",
"fallback": ["en"]
},
"query": {}
}Result: Returns Italian translation if available, otherwise English. If neither exists, returns no results.
Note: Empty query object matches all documents, filtered by language.
Fallback to source language
Return English articles, falling back to Spanish, then to source language if neither available:
{
"language": {
"primary": "en",
"fallback": ["es"],
"default": true
},
"query": {
"text": {
"query": "championship",
"path": "heroMedia.title"
}
}
}Result: Returns English if available. If not, tries Spanish. If neither exists, returns article in its original source language (could be German, French, etc.).
Strict language matching (no fallback to source)
Return only English or Spanish articles, exclude articles without these translations:
{
"language": {
"primary": "en",
"fallback": ["es"],
"default": false
},
"query": {
"text": {
"query": "championship",
"path": "heroMedia.title"
}
}
}Result: Returns English if available, otherwise Spanish. If neither exists, the article is excluded from results (even if it exists in other languages).
Notes
- The
languageoperator is mutually exclusive with direct language field filtering in your query. When usinglanguage, it is not recommended to also filter by thelanguagefield within yourquery. - Language codes are case-sensitive and should follow standard conventions.
- Locale codes use hyphens (e.g.,
fr-ca, notfr_ca) - You can mix two-letter and four-character codes (e.g.,
"primary": "fr-ca", "fallback": ["fr", "en"]) - The source language is the language in which the article was originally authored
Updated about 2 hours ago
