TL;DR
Currently the NodeSearchServiceInterface allow to search by term (sql like in all properties), and limit the search by nodeType and context. It’s really limited and need to be extended in a flexible way to allow advanced search like in https://github.com/neos/neos-development-collection/pull/5
The current implementation do not enforce a limit, some query can return a huge amount of node and can hit the memory or time limit.
Goal
- Allow more flexible search implementation (by specific property, multiple properties, …)
Technical how
- Based on JSON-API (http://jsonapi.org/format/#fetching-filtering), use a filter query parameter, with this implementation:
- If filter is a string: same behavior as the current term query parameter (search in all properties, like statement)
- If filter is an array: the key is the property name, the value the search query for this property. The value can be an array (this replace the current $searchNodeTypes, by
filter[_nodeType][]=FirstNodeType&filter[_nodeType][]=SecondNodeType
, by default use a OR operator - If filter is an array, internal property can queried by prefixing the property name by
_
- Search query is by default a like, ex. ```%term%``, see Query Vocabulary bellow
- Add support to search by sub property in the JSON, see Query Vocabulary bellow
- Add a default limit (ex: 20), based on http://jsonapi.org/format/#fetching-pagination (support for both page[number] and page[size] + page[offset] and page[limit])
- Add support for sorting, based on http://jsonapi.org/format/#fetching-sorting
- Keep the context parameter
Sorting
Currently only for some internal property, like modification time, can be improved in the futur.
Sparse Fieldsets
See: http://jsonapi.org/format/#fetching-sparse-fieldsets
Not supported currently, but reserved for futur implementation
Query Vocabulary
As JSON-API doesn’t specify a query voc. we have some freedom here
Required
- Full text:
filter[property]=term
- Begin with:
filter[property]=%term
- End with:
filter[property]=term%
- Equal (exact match):
filter[property]="term"
All query must be case insensitive
Nice to have
Maybe require custom implementation for MySQL and PostgreSQL to use JSON capabilities of the DB.
- Sub property query:
filter[property.subproperty]=%term
This can be added in the next iteration without changing the interface.
New Interface
interface NodeSearchServiceInterface
{
/**
* @param string|array $filter
* @param Context $context
* @param integer $limit
* @param integer $offset
* @param string $sort
* @return array<NodeInterface>
*/
public function findByProperties($filter, Context $context, $limit = 20, $offset = null, $sort = null);
}
Benefits
- Simple and flexible interface
- More powerful search query can be build without changing the interface
- Avoid high memory /resource usage (limit)
Challenges
- Did we need the AND operator for a single property (see the exemple with
_nodeType
) - The search vocabulary need to be common to all implementations, to be able to switch the implementation at any point