-
-
Notifications
You must be signed in to change notification settings - Fork 3
Proposal
Adding advanced filtering to JSONAPI via a top-level filter
parameter which accepts a string representation of an MongoDB query object, highly optimised for the kinds of queries which are common to Ghost, but flexible enough to grow outside of anticipated use cases.
A top-level filter
parameter will provide advanced querying capabilities available in varying contexts in a standard way, such that the parameter's value is always a string:
- HTTP:
GET /api/posts?limit=5&filter=???
- Method Call:
api.posts.browse({limit: 5, filter: '???'})
- Handlebars Helper:
{{#get "posts" limit="5" filter="???"}}
Careful handling of quotes, and the ability to URL encode are a requirement.
- Pojo Example:
apiOptions = {
filter: 'slug:-' + slug + '+published_at:' + op + '\'' + publishedAt + '\'
};
- Pojo ES6 Example:
apiOptions = {
filter: `slug:-${slug}+published_at:${op}'${publishedAt}'`
};
The key requirement of NQL is to parse values which can represent a MongoDB query object. The fundamentals of this proposal are therefore the definition of a language which fits Ghost's use cases and can be converted into MongoDB JSON.
MongoDB Query capabilities are extensive. To start with, the focus for Ghost is on supporting logical and & or combinations, comparisons using equals, greater than & less than (with support for not). The importance of the relation between Post & Tags also drives the need to support in.
An individual filter clause is composed of 3 parts, the property that is being filtered, the operator and the value. Filters need to be combined in groups of or & and rules.
The property needs to support aliasing: e.g. tag
currently really means tag.slug
.
The operators need to include equals, not equals, and numerical comparisons.
The values are strings, numbers, nulls etc that are matched/compared against.
There are a number of common styles for combining properties, operators and values into expressions. This proposal borrows heavily from the style used in GitHub, Gmail & Slack amongst others: E.g.label:api
or from:-hannah
or stars:<10
.
The syntax of this style is the use of property-operator-value triplets in the form: property:operatorvalue, where the colon is a separator, and operator is optional.
This syntax is short and compact for the common use cases in Ghost, for example: featured:true
, tags:photo
, author:john
, image:-null
, posts.count:>10
This syntax is also flexible enough to be extended to support multiple complex expressions by combining the property-operator-value triplets together with other symbols to represent and & or. Following on from using -
for negation, the proposal is to use +
for and as well as ,
for or e.g: featured:true+tags.count:>10
, tags:photo,tags:video
.
This is then used inside of the filter=""
parameter, E.g:
- HTTP:
GET /api/posts?limit=5&filter=tags:photo,featured:true
- Method Call:
api.posts.browse({limit: 5, filter: "tags:photo,featured:true"})
- Get Helper:
{{#get "posts" limit="5" filter="tags:photo,featured:true"}}