Added in: release-2023-07
Display Filter Migration
The structure of display filters has changed. Instead of the typical type
and value
properties alongside the label
there are now three distinct properties that can be used to change the filter functionality. The main one is the filter
property, which is an object containing the filter query using the new Search Filters Query DSL. There is also a context
property which can be used by Custom Filters. Finally, there is a sort
property, which is a string that replaces the 'sortBy'
filter type.
Type/Value Filters
The type/value
combination should be migrated to new filter
attribute:
{
- id: 'published',
label: 'Published Documents',
- type: 'documentState',
- value: 'published'
+ filter: {key: 'lastPublicationId', exists: true}
}
For additional filter examples please see the Migration Examples section below.
Custom Filters
Migrate the customFilter
value to the new context
attribute:
{
- id: 'published',
label: 'My Custom Filter',
- type: 'customFilter',
- value: {foo: 'bar'}
+ context: {foo: 'bar'}
}
SortBy Filter
Migrate the sortBy
value to the new sort
attribute:
{
- id: 'sortByUpdated',
label: 'Recently updated documents first',
- type: 'sortBy',
- value: '-updatedAt'
+ sort: '-updatedAt'
}
Base Filter Migration
Base Filters have not changed as significantly as Display Filters, as they are equivalent to the filters
property within the Display Filter options. The same Search Filters Query DSL is used within the object.
Sorting
The 'sortBy'
filter should be replaced with a sort
property on the root of the dashboard config:
{
type: 'tableDashboard',
handle: 'gallery-dashboard',
pageTitle: 'Gallery Board',
// ...
- baseFilters: [
- {type: 'contentType', value: 'gallery'},
- {type: 'sortBy', value: '-updatedAt'}
- ],
+ sort: '-updatedAt',
+ baseFilters: [
+ {key: 'contentType', term: 'gallery'}
+ ]
}
Filtering
The filter configuration has changed from type
and value
properties to key
and query expressions. The current supported query expressions are term
, range
and exists
.
A simple legacy filter might look like this:
{type: 'contentType', value: 'regular'}
The new filter should look like this:
{key: 'contentType', term: 'regular'}
Below you will find specific examples of how to migrate different legacy filters. These objects can be used for baseFilters
, the displayFilters
filters
property, and for Public API Search Filters.
Migration Examples
Simple Key/Value Filters
As mentioned above, these are straightforward to migrate. The type
property should be renamed to key
, and the value
property should be renamed to term
.
The values should be of the correct type, so string
for 'contentType'
, 'documentType'
, 'mediaType'
, 'reference'
, and integer
for id
, channelId
, ownerId
, createdBy
. An array of values can also be passed, or you can use a range
query expression, or exists
if you want to know if the property has been indexed.
metadata
Metadata queries will vary based on the desired query expression and the value type.
For metadata values which are stored as objects you must always use a nested property to check if it exists.
For example, if you would like to check if a task has been defined you should use {key: 'metadata.myTaskHandle.state', exists: true}
. Using {key: 'metadata.myTaskHandle', exists: true}
will throw an error because the field 'metadata.myTaskHandle'
is not indexed, only the individual properties within it such as 'metadata.myTaskHandle.state'
.
References
References are stored as keywords, so you can use any of the query expressions listed below. The important thing to remember is to query the nested reference property where the id is stored, and not the top-level metadata handle.
{key: 'metadata.myDocumentReference.reference.id', term: 1}
{key: 'metadata.myDocumentReferences.references.id', term: 1}
{key: 'metadata.myCategory.id', term: 1}
{key: 'metadata.myVideoReference.reference.id', term: ['abc123', 'def456']}
Value / Term
For standard term queries you should provide the correct value type, depending on the indexing config of the metadata plugin. You can also provide an array of values.
Before:
{type: 'metadata', key: 'myMetadataHandle', value: 'myValue'}
{type: 'metadata', key: 'myMetadataHandle', value: 1}
{type: 'metadata', key: 'myMetadataHandle', value: ['myFirstValue', 'mySecondValue']}
After:
{key: 'metadata.myMetadataHandle', term: 'myValue'}
{key: 'metadata.myMetadataHandle', term: 1}
{key: 'metadata.myMetadataHandle', term: ['myFirstValue', 'mySecondValue']}
Exists
Previously there was support for exists
and value.exists
properties, but this is now just the top-level exists
, along with the key
:
Before:
{type: 'metadata', key: 'myMetadataHandle', exists: true}
{type: 'metadata', key: 'myMetadataHandle', value: {exists: false}}
After:
{key: 'metadata.myMetadataHandle', exists: true}
{key: 'metadata.myMetadataHandle', exists: false}
Date Range / Range
The dateFilter
and rangeFilter
properties have been replaced by the range
property. If you’re also using from
and to
you should replace them with gte
and lte
:
Before:
{type: 'metadata', key: 'myMetadataHandle', dateFilter: {from: '2023-07-04T00:00:00.000Z', to: '2023-07-04T23:59:59.999Z'}}
{type: 'metadata', key: 'myMetadataHandle', rangeFilter: {from: '2023-07-04T00:00:00.000Z', to: '2023-07-04T23:59:59.999Z'}}
After:
{key: 'metadata.myMetadataHandle', range: {gte: '2023-07-04T00:00:00.000Z', lte: '2023-07-04T23:59:59.999Z'}}
{key: 'metadata.myMetadataHandle', range: {gte: '2023-07-04T00:00:00.000Z', lte: '2023-07-04T23:59:59.999Z'}}
The optional: true
parameter requires an OR filter to check for the existence of the value:
Before:
{type: 'metadata', key: 'myMetadataHandle', dateFilter: {gte: '2023-07-04T00:00:00.000Z', lt: '2023-07-05T00:00:00.000Z', optional: true}}
After:
{or: [
{key: 'metadata.myMetadataHandle', exists: false},
{key: 'metadata.myMetadataHandle', range: {gte: '2023-07-04T00:00:00.000Z', lt: '2023-07-05T00:00:00.000Z'}}
]}
See Date Range for more examples.
locale
The 'locale'
filter type has been renamed to 'language'
:
Before:
{type: 'locale', value: 'en'}
{type: 'locale', value: ['en', 'de']}
After:
{key: 'language', term: 'en'}
{key: 'language', term: ['en', 'de']}
notContentTypeBefore:
For NOT queries you can use the new logical operator in the Filter Query DSL:
Before:
{type: 'notContentType', value: 'author'}
{type: 'notContentType', value: ['author', 'page']}
After:
{not: {key: 'contentType', term: 'author'}}
{not: {key: 'contentType', term: ['author','page']}}
dateRange
The new range
property supports gte
, lte
, gt
, and lt
:
Before:
{type: 'dateRange', key: 'myDateHandle', gte: '2023-07-04T00:00:00.000Z'}
{type: 'dateRange', key: 'myDateHandle', gte: '2023-07-04T00:00:00.000Z', lte: '2023-07-04T23:59:59.999Z'}
{type: 'dateRange', key: 'myDateHandle', gt: '2023-07-03T23:59:59.999Z', lt: '2023-07-05T00:00:00.000Z'}
{type: 'dateRange', key: 'myDateHandle', gte: '2023-07-04T00:00:00.000Z', lt: '2023-07-05T00:00:00.000Z'}
After:
{key: 'myDateHandle', range: {gte: '2023-07-04T00:00:00.000Z'}}
{key: 'myDateHandle', range: {gte: '2023-07-04T00:00:00.000Z'}}
{key: 'myDateHandle', range: {gte: '2023-07-04T00:00:00.000Z', lte: '2023-07-04T23:59:59.999Z'}}
{key: 'myDateHandle', range: {gt: '2023-07-03T23:59:59.999Z', lt: '2023-07-05T00:00:00.000Z'}}
{key: 'myDateHandle', range: {gte: '2023-07-04T00:00:00.000Z', lt: '2023-07-05T00:00:00.000Z'}}
Instead of from
and to
, gte
and lte
should be used:
Before:
{type: 'dateRange', key: 'myDateHandle', from: '2023-07-04T00:00:00.000Z', to: '2023-07-04T23:59:59.999Z'}
After:
{key: 'myDateHandle', range: {gte: '2023-07-04T00:00:00.000Z', lte: '2023-07-04T23:59:59.999Z'}}
published
To see if a document is currently published you can check if lastPublicationId
exists:
Before:
{type: 'published', value: true}
{type: 'published', value: false}
After:
{key: 'lastPublicationId', exists: true}
{key: 'lastPublicationId', exists: false}
documentState
The various 'documentState'
filters can be replicated using other available properties:
Before:
{type: 'documentState', value: 'published'}
{type: 'documentState', value: 'unpublished'}
{type: 'documentState', value: 'draft'}
{type: 'documentState', value: 'publishedWithDraft'}
{type: 'documentState', value: 'scheduledOrPublished'}
After:
{key: 'lastPublicationId', exists: true}
{key: 'lastPublicationId', exists: false}
{key: 'hasDraft', term: true}
{and: [{key: 'hasDraft', term: true}, {key: 'lastPublicationId', exists: true}]}
{or: [{key: 'lastPublicationId', exists: true}, {key: 'publishControl.publishSchedule.date', exists: true}]},
userInTeam
To recreate the 'userInTeam'
filter type there is a special termPattern
property which uses the current user’s id:
Before:
{type: 'userInTeam', key: 'myTeamHandle'}
After:
{key: 'metadata.myTeamHandle.activeUsers.id', termPattern: '{{ userId }}'}
buyInNotExpired
The 'buyInNotExpired'
replacement uses a relative time range:
Before:
{type: 'buyInNotExpired', key: 'myBuyInHandle'}
After:
{key: 'metadata.myBuyInHandle.workflow.expiryDate', range: {gte: 'now/d'}}
The /d
rounds to the start of the day. Along with 'now/d'
there is also support for 'now'
, 'now-1d'
, and 'now-1d/d'
.