Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@e0ipso
Last active August 29, 2015 15:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save e0ipso/1acbced683908ff631e3 to your computer and use it in GitHub Desktop.
Save e0ipso/1acbced683908ff631e3 to your computer and use it in GitHub Desktop.
JSON API compound filters extension

Relational filters JSON API extension

This extension provides documentation on how to filter based on relationships.

Given a requested resource (resource from now on) that contains several relationships (rel1, rel2, … from now on), you can apply filters on the resource based on conditions on rel1, rel2, … The default behavior is to filter the elements on resource, unless otherwise is specified.

The following request returns only the resource entities that contain a relationship that meets the filter:

GET /resource?filter[rel1.conditionField][value]=value1
- or -
GET /resource?filter[rel1.conditionField]=value1

In the example above conditionField is a field that exists in the rel1 resource. Only the resource entities that contain at least one rel1 entity with conditionField having value1 SHOULD be returned. Every resource entity returned will contain all of its rel1 entities, regardless of their conditionField value.

To alter the default behavior, the user can provide the target of the filter. The target can be the resource containing the condition field, or any of its parents until the –top level– resource.

The following request returns all of the resource entities, compounding only the ones that meet the filter:

GET /resource?filter[rel1.conditionField][value]=value1&filter[rel1.conditionField][target]=rel1

In the example above, all resource entities are returned. Each resource entity will only contain the rel1 entities with conditionField having value1.

For a filter on the filter rel1.relA.relAlpha.rel.conditionField the allowed targets are: rel1, rel1.relA, rel1.relA.relAlpha, and rel1.relA.relAlpha.rel. The target resource, is the one whose items may be filtered out.

Extension name

e0ipso/relational-filters

See the extension spec for more information about extensions.

@deviantintegral
Copy link

A few minor typos on contidionField, taget.

In the example above, all resource entities are returned. Every returned resource entity will only contain the rel1 entities with contidionField having value1.

These sentences contradict each other ("all resource entities").

I'm confused by the point of target. Can you explain some more?

I'd be concerned about allowing arbitrary relationship joins, given how often json-api will be used against document stores and not relational databases. But I suppose that could be a per-implementation detail to throw a 4XX if you nest too deeply.

@e0ipso
Copy link
Author

e0ipso commented Aug 26, 2015

These sentences contradict each other ("all resource entities").

I changed it to be: In the example above, all resource entities are returned. Each resource entity will only contain the rel1 entities with conditionField having value1.

@e0ipso
Copy link
Author

e0ipso commented Aug 26, 2015

I'm confused by the point of target. Can you explain some more?

The problem is that if you add a filter on a field for an embedded resource there is ambiguity. You may want to limit the number of embedded entities, or you may want to limit the results of the top level resource. Adding target aims to remove that ambiguity.

@e0ipso
Copy link
Author

e0ipso commented Aug 26, 2015

I'd be concerned about allowing arbitrary relationship joins, given how often json-api will be used against document stores and not relational databases. But I suppose that could be a per-implementation detail to throw a 4XX if you nest too deeply.

JSON API defines the includes in their spec. This only adds some common ground for filters in related entities. In any case, this is an extension of the official specification client should provide this extension code (mateu-aguilo-bosch/relational-filters) in the Accept header to opt-in to this behavior.

@helior
Copy link

helior commented Aug 26, 2015

For a filter on the filter rel1.relA.relAlpha.rel.conditionField the allowed targets are: resource (default), rel1, relA, relAlpha, and rel. The target resource, is the one that is limited.

The allowed targets here suggest that relationship names must be unique across the relationship chain. I would suggest that we continue to follow the dot-notation for target values to avoid the following ambiguity:

A collection that promotes a season and a set of selected episodes; it would have a direct relationships with a season and episodes (the episodes won't necessarily be of the same season, but could be all the episodes that highlight a particular character's development):
Collections → season
Collections → episodes

While that episode could also has a relationship to it's season:
Episodes → season

The season target in this case is ambiguous for either of these relationships:
Collections → episodes → season
Collections → season

@helior
Copy link

helior commented Aug 26, 2015

Some of the wording was a bit confusing, as Andrew pointed out. But overall I think this approach is good.

@e0ipso
Copy link
Author

e0ipso commented Aug 29, 2015

@helior, @deviantintegral can you point out the confusing wording? :yoda: 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment