Searching and Filtering

How to search, and construct complex filters for any query.

Searching is an inherently inclusive operation, whereby the system will add all records whose values closely - but not exactly - match the search string. Filtering, by contrast, constrains the set of records to those that exactly match the provided values, though they may support wildcards. They can operate in tandem, with a filter constraining the field in which a search is applied, but care must be taken that the system can handle the complexity of the combined operation.

Searching

A search string is provided by a user when they are not entirely certain where the result they are seeking is expressed. For example, a word expressed in a search string may exist in a title, a description, or any other property of the resource.

POST /v1/resources/query HTTP/1.1

{
  "search": "...."
}
PropertyRelevanceTypeDescription
searchrequeststringA string by which to search in the set of resources.

It is left to each resource type to define which fields are included in the search index, and what tokenization method is used to decompose the resource instance and the incoming search expression. In all cases, the result should be a ' best fit’ match, should be case-insensitive, and should be returned in the order of most relevant first.

Filter

A query may include a filter object, which expresses a tree-like structure of logical filters and their relevant operands. There are two basic types of filter objects: single and multiple. If a search string is also provided, it must only be applied to resources that also match the filters.

If a search string is provided, and the query also accepts sorting criteria, the service must return a 400 Bad Request stating that search and sort are not compatible. Searching already includes an implicit sort based on the relevance of each record, which a sort expression would conflict with. These two expressions are not compatible.

Single Value Operation

Filtering for a single value on a single field looks as follows:

POST /v1/resources/query HTTP/1.1

{
  "filters": {
        "op": "....",           // the logical operation that applies to a single value (see below)
        "key": "dot.notation",  // The key where the value should be found, using dot-notation for deep nesting.
        "value": "some-value"   // The input value of for the logical operation, if appropriate.
    }
}

Multi-Value Operation

Filtering on multiple criteria would expand on the above.

POST /v1/resources/query HTTP/1.1

{
  "filters": {
        "op": "....",           // the logical operation that applies to multiple values.
        "values": [
            {
                // A list of single or multi-value operations.
            }
        ]
    }
}

Data Schema

KeyTypeRelevanceDescription
opstringAllThe operation to perform. Case insensitive, see below for a full list of required operations. If not provided, the default value is assumed to be EQ for single values, and OR for multi values.
keystringSingle ValueThe property on which to perform the operation, which may include dot-notation.
valuestringSingle ValueA value to use for single-value operations.
valuesFilter ArrayMulti ValueA list of operations. If an empty array is included, no records should match.

The value property is always a string, though its format may be type specific:

  • Dates must be formatted as RFC-3339.
  • String values may include the wildcard *, which represents zero or more of any character.
  • Large numbers (big.Int) must be expressed as base64 encoded strings.
  • Regular Expressions must not include leading and trailing slashes.

Valid Operations

OperationKey NameRelevanceNotes
EQStrictly EqualsSingle Value
NEQNot EqualsSingle Value
GTGreater ThanSingle Value
LTLess ThanSingle Value
GEGreater or Equal ToSingle Value
LELess than or Equal ToSingle Value
REGEXRegular ExpressionSingle Value
ANDAndMulti ValueAll of the provided filters must be true.
OROrMulti ValueAny of the provided filters must be true.
XORExclusive orMulti ValueOnly one of the provided filters may be true.
XNORAll or nothingMulti ValueAll of the provided filters must be true, or false.

Wildcards

The use of wildcards may be used in string values, using simple Glob matching. For more complex queries, use the REGEX operation.

Wildcard CharacterOperation
*One or more of any character.
?Any single character.

Examples

String Equality

{
  "filters": {
    "op": "OR",
    "values": [
      // EQ is the default
      {
        "key": "name",
        "value": "some_value"
      },
      {
        "key": "name",
        "value": "some_other_value"
      }
    ]
  }
}

Date Range

{
  "filters": {
    "op": "AND",
    "values": [
      {
        "op": "GT",
        "key": "createdDate",
        "value": "1985-04-12T00:00:00Z"
      },
      {
        "op": "LE",
        "key": "createdDate",
        "value": "1985-04-12T23:59:59Z"
      }
    ]
  }
}