Data types and value formats
Content Advanced Search supports various data types for querying articles and pages. This document outlines each supported type and the value formats you can use.
Text
Full-text analysed string fields that are tokenised and suitable for search queries.
Fields: heroMedia.title, heroMedia.summary, content.text, content.altText, etc.
Value format:
"value": "some text"Supported operators:
| Operator | Description |
|---|---|
text | Full-text search with tokenisation, stemming, and relevance scoring |
phrase | Exact phrase matching (words in order) |
prefix | Match values starting with a prefix |
exists | Check if field exists |
Characteristics:
- Tokenised and analysed during indexing
- Case-insensitive by default
- Supports fuzzy matching and relevance scoring
- Best for human-readable content and search
Examples:
{
"text": {
"query": "tournament final",
"path": "heroMedia.title"
}
}{
"phrase": {
"query": "championship victory",
"path": "content.text"
}
}Keyword
Exact-value string fields stored as-is without analysis. Used for filtering and sorting.
Fields: slug, language, tags, categories.id, linkedIds.sourceSystem, linkedIds.sourceSystemId, etc.
Value format:
"value": "exact-value"Supported operators:
| Operator | Description |
|---|---|
equal | Exact value matching (case-sensitive) |
in | Match any value from a list |
range | Lexicographic (alphabetical) range queries |
prefix | Match values starting with a prefix |
exists | Check if field exists |
Characteristics:
- Stored exactly as provided
- Case-sensitive matching
- No tokenisation or analysis
- Best for structured data, IDs, slugs, tags, and enum values
Examples:
{
"equal": {
"path": "slug",
"value": "article-slug"
}
}{
"in": {
"path": "tags",
"values": ["breaking-news", "exclusive", "featured"]
}
}{
"equal": {
"path": "linkedIds.sourceSystem",
"value": "OPTA_FOOTBALL_TEAM"
}
}Number
Numeric values including integers and floating-point numbers.
Fields: readTimeMinutes, etc.
Value format:
"value": 123or
"value": 45.67Supported operators:
| Operator | Description |
|---|---|
equal | Exact value matching |
in | Match any value from a list |
range | Numeric range queries with gte, gt, lte, lt |
exists | Check if field exists |
Examples:
{
"range": {
"path": "readTimeMinutes",
"gte": 5,
"lte": 15
}
}Boolean
True or false values.
Fields: pinned, singlePage, custom boolean fields, etc.
Value format:
"value": trueor
"value": falseSupported operators:
| Operator | Description |
|---|---|
equal | Exact value matching |
exists | Check if field exists |
Examples:
{
"equal": {
"path": "pinned",
"value": true
}
}{
"equal": {
"path": "singlePage",
"value": false
}
}Date
Date and datetime values following ISO 8601 format with nanosecond precision.
Fields: publishDate, lastModified.date
Standard format: ISO 8601
YYYY-MM-DD
YYYY-MM-DDTHH:mm:ss
YYYY-MM-DDTHH:mm:ssZ
YYYY-MM-DDTHH:mm:ss.sssZ
YYYY-MM-DDTHH:mm:ss.sssssssssZ (nanosecond precision)
Date math expressions: Relative dates anchored to now or an absolute date
now
now-30d
now-1M
now+2h
now-1y+6M/d
2026-01-01||+30d
2026-01-01T00:00:00Z||-1M+5d/d
Supported operators:
| Operator | Description |
|---|---|
equal | Exact date matching |
in | Match any date from a list |
range | Date range queries with gte, gt, lte, lt |
exists | Check if field exists |
Date Math Syntax
Two anchor forms are supported:
| Anchor | Description |
|---|---|
now | Resolved to the current time at query-execution time |
<date>|| An absolute ISO 8601 date/datetime resolved at parse time |
The anchor can be followed by zero or more +<value><unit> / -<value><unit> segments and an optional /d rounding suffix:
now[+-<value><unit>]*[/d]
<date>||[+-<value><unit>]*[/d]
Multiple segments are applied left to right: now-1y+6M-3d/d
/d rounding: Truncates the result to midnight (00:00:00) after all offsets have been applied.
Supported units:
| Unit | Description |
|---|---|
y | Years |
M | Months (capital M) |
w | Weeks |
d | Days |
h | Hours |
m | Minutes (lowercase m) |
s | Seconds |
Examples:
Absolute dates:
{
"range": {
"path": "publishDate",
"gte": "2024-01-01",
"lte": "2024-12-31"
}
}Relative dates:
{
"range": {
"path": "publishDate",
"gte": "now-30d"
}
}Complex date math (multiple segments + rounding):
{
"range": {
"path": "publishDate",
"gte": "now-1M",
"lte": "now/d"
}
}Anchor date with math:
{
"range": {
"path": "publishDate",
"gte": "2026-01-01||+30d",
"lte": "2026-01-01||+60d/d"
}
}Common Date Patterns
| Pattern | Description |
|---|---|
now | Current date and time |
now/d | Today at midnight (UTC) |
now-1d | 1 day ago |
now-7d | 7 days ago (last week) |
now-30d | 30 days ago (last month) |
now-1M | 1 month ago |
now-3M | 3 months ago (last quarter) |
now-1y | 1 year ago |
now-24h | 24 hours ago |
now+1d | 1 day from now (future) |
now+1w | 1 week from now |
now-1y+6M/d | 6 months ago from a year ago, at midnight |
2026-01-01|| | Absolute anchor with no offset |
2026-01-01||+30d | 30 days after 1 Jan 2026 |
Timezone Handling
- The
nowkeyword is evaluated using UTC timezone - Dates without timezone information (e.g.,
2024-01-01,2024-01-01T10:30:00) are interpreted as UTC - To specify a different timezone, include the timezone offset in the date string:
2024-01-01T00:00:00-05:00(EST)2024-01-01T00:00:00+01:00(CET)
- For consistent behaviour across all queries, it's recommended to always include timezone information or use UTC
Timezone examples:
Find articles published after midnight EST (5 hours behind UTC):
{
"range": {
"path": "publishDate",
"gte": "2024-11-10T00:00:00-05:00"
}
}Compare with UTC equivalent (5 hours later):
{
"range": {
"path": "publishDate",
"gte": "2024-11-10T05:00:00Z"
}
}Both queries are equivalent - the first midnight EST equals 5 AM UTC.
Use cases:
Last 7 days:
{
"range": {
"path": "publishDate",
"gte": "now-7d",
"lte": "now"
}
}This month:
{
"range": {
"path": "publishDate",
"gte": "now-1M"
}
}Between specific dates:
{
"range": {
"path": "publishDate",
"gte": "2024-06-01T00:00:00Z",
"lt": "2024-07-01T00:00:00Z"
}
}Null
Represents the absence of a value.
Value format:
"value": nullSupported operators:
| Operator | Description |
|---|---|
equal | Match null values |
exists | Check if field exists (note: null values are considered non-existent) |
Example:
{
"equal": {
"path": "heroMedia.summary",
"value": null
}
}Note: To check if a field exists regardless of value, use the exists operator instead.
Nested
Complex objects containing multiple fields. Nested types preserve the relationship between fields within each object in an array.
Fields: categories, linkedIds, sponsors, author.socialHandles, content.linkedIds
Structure: Nested fields are arrays of objects where each object has its own set of properties:
"categories": [
{
"id": "5a3c1e8b-4f2d-4a1c-9b8e-1234567890ab",
"text": "Division One"
}
]"linkedIds": [
{
"sourceSystem": "OPTA_FOOTBALL_TEAM",
"sourceSystemId": "t123"
}
]Supported operators:
| Operator | Description |
|---|---|
nested | Query nested objects while preserving field relationships |
| Individual operators | Use within nested context (text, equals, range, etc.) |
When to use the nested operator:
| Scenario | Required? | Reason |
|---|---|---|
| Multiple fields in same nested object | Required | Ensures all conditions match on a single object |
| Single field in nested object | Optional | e.g., just categories.id |
Basic example:
{
"nested": {
"path": "linkedIds",
"query": {
"compound": {
"filter": [
{
"equal": {
"path": "linkedIds.sourceSystem",
"value": "OPTA_FOOTBALL_TEAM"
}
},
{
"equal": {
"path": "linkedIds.sourceSystemId",
"value": "t123"
}
}
]
}
}
}
}For complete details, examples, and best practices, see the nested operator documentation.
Type Coercion and Validation
Advanced Search performs basic type validation:
| Field Type | Accepted Values |
|---|---|
| Boolean | true or false |
| Numeric | Numbers (integers or floats) |
| Date | ISO 8601 format or date math expressions |
| Keyword | Any text value (exact match) |
| Text | Any text value (analysed) |
Type mismatches will result in no matches or query errors.
Examples by type
Working with Booleans
Find pinned articles that are not pages:
{
"query": {
"compound": {
"filter": [
{
"equal": {
"path": "pinned",
"value": true
}
},
{
"equal": {
"path": "singlePage",
"value": false
}
}
]
}
}
}Working with numbers
Find articles with read time between 5 and 10 minutes:
{
"query": {
"range": {
"path": "readTimeMinutes",
"gte": 5,
"lte": 10
}
}
}Working with dates
Find articles published in the last 24 hours:
{
"query": {
"range": {
"path": "publishDate",
"gte": "now-24h"
}
}
}Find articles published in a specific month:
{
"query": {
"range": {
"path": "publishDate",
"gte": "2024-10-01T00:00:00Z",
"lt": "2024-11-01T00:00:00Z"
}
}
}Working with text fields
Full-text search across title and content body:
{
"query": {
"text": {
"query": "tournament championship",
"path": ["heroMedia.title", "content.text"]
}
}
}Exact phrase match:
{
"query": {
"phrase": {
"query": "breaking news",
"path": "heroMedia.title"
}
}
}Working with keyword fields
Find articles with specific tags:
{
"query": {
"in": {
"path": "tags",
"values": ["breaking-news", "exclusive", "featured"]
}
}
}Exact match on slug:
{
"query": {
"equal": {
"path": "slug",
"value": "article-slug-2024"
}
}
}Prefix search on slug:
{
"query": {
"prefix": {
"query": "article-",
"path": "slug"
}
}
}Working with null
Find articles where a field is not set:
{
"query": {
"equal": {
"path": "heroMedia.summary",
"value": null
}
}
}Working with nested objects
Find articles in a specific category:
{
"query": {
"nested": {
"path": "categories",
"query": {
"equal": {
"path": "categories.id",
"value": "5a3c1e8b-4f2d-4a1c-9b8e-1234567890ab"
}
}
}
}
}Find articles linked to a specific entity from a specific source:
{
"query": {
"nested": {
"path": "linkedIds",
"query": {
"compound": {
"must": [
{
"equal": {
"path": "linkedIds.sourceSystem",
"value": "OPTA_FOOTBALL_TEAM"
}
},
{
"equal": {
"path": "linkedIds.sourceSystemId",
"value": "t123"
}
}
]
}
}
}
}
}Find articles with specific categories:
{
"query": {
"equal": {
"path": "categories.id",
"value": "a1b2c3d4-e5f6-4a5b-8c7d-9e0f1a2b3c4d"
}
}
}Best practices
- Use text fields for search, keyword fields for filtering - Use
textoperator on analysed text fields,equalon keyword fields - Know your field types - Text fields are case-insensitive and analysed, keyword fields are exact and case-sensitive
- Use nested queries for related fields - Always use
nestedoperator when querying multiple fields within the same nested object - Use date math for relative queries - Prefer
now-7dover hardcoded dates for "last 7 days" queries - Be explicit with date ranges - Use both
gteandltewhen you need a bounded range - Match field types - Ensure your query values match the field's data type
- Use ISO 8601 for absolute dates - Include timezone information when possible
- Consider timezone handling -
nowuses the server's current time
Updated about 2 hours ago
