What if a sparse fieldset request excludes a field that was requested for inclusion?


#1

Consider a request that supplies both a request for inclusion of a related record include=author and excludes the same field through a sparse fieldset fields[post]=title.

How should one respond to such a query? We currently reject the request with a status of 400, but I would like to hear how others see it.


#2

Sparse fieldsets are constrained by their TYPE.

A client MAY request that an endpoint return only specific fields in the response on a per-type basis by including a fields[TYPE] parameter.

As such, the inclusion of fields[post]=title does not constitute a contradiction as sparse fieldsets only perform data shaping upon items which would have made it into the document after content processing including filter and ‘includes’ is completed.

Therefor the only contradiction possible would be if the fieldsets were declared multiple times, in which case you could reject with 400, or serve the request with the aggregated fieldset.

HOWEVER, it looks like you’re using includes to perform sparse fieldsets, or at least think it has that capability, where it is strictly about defining which related resources not attributes are to be added in the ‘includes’ section of the TLD.

Includes is for document shaping and eliminating extraneous calls, sparse fieldsets are for performing data shaping upon those returned types.


#3

Maybe my example wasn’t ideal. Let me elaborate.

I’m assuming post has a relationship to a person, the author. It also has a attribute title, which is a string.

It is my understanding that sparse fieldsets have an impact on both relationships and attributes. Thus, a sparse fieldset definition may exclude information that is relevant to the consistency of the relationship.
So my example was trying to say “Give me only the title of the post, but include the author of the post in the document”.

You say that the sparse fieldset is only intended to shape the final resulting document. If that is the case, then I agree, there is no contradiction. However, I did not interpret it that way and implemented it so that the field selection is the basis for storage queries. So I only retrieve the fields that I will use in the resulting document. This way, I’m now possibly missing information which I would require to include the requested resources. Possibly a mistake.

Additionally, if I were to include the referenced records, but strip away the relationship information to satisfy the sparse fieldset request, would that not hurt the full-linkage goal?

Thanks for the feedback :slight_smile:


#4

I believe the issue boils down to how to present the type as requested in the fields parameter, while maintaining full linkage.

The primary data would of course always include everything, unless sparse fieldsets is used to reduce it. However, full linkage must be maintained so the appropriate resource objects with nothing more than type, id, and links to build the chain from primary data to the included resource.

The way I view include in this context is essentially a pre-fetch operation to batch the request for related resources without the need to individually request the items through relationship identifiers. It essentially is performing multiple requests in one. Sparse fieldsets then takes the document and reduces the result to the requested resources + any required objects for full linkage.

I have also had the urge to use sparse fieldsets to reduce the load on storage, so my advice would be to use the approach of returning minimum linkage + whatever is requested in the case of conflicting statements. In this way you would be able to retrieve all the keys required for full linkage, without including any of the unrequested data. This would still satisfy full linkage, as well the sparse fieldsets request.

Using the example you listed should yield something like this.

GET http://www.example.com/post/1?include=author&fields[post]=title

{
  "type": "post",
  "id": "1",
  "attributes": {
    "title": "It's a title."
  },
  "relationships": {
    "author": {
      "links": {
        "self": "http://example.com/articles/1/relationships/author",
        "related": "http://example.com/people?filter[article]=1"
      },
      "data":{
        "type":"people", "id":"9"
      }
    }
  },
  "included":[
    {
      "type":"people",
      "id": "9",
      "attributes": {
        "first-name": "Dan",
        "last-name": "Gebhardt",
        "twitter": "dgeb"
      },
      "links": {
        "self": "http://example.com/people/9"
      }
    }
  ],
  "links": {
    "self": "http://example.com/articles/1"
  }
}

Include is used to declare how far out on a particular relationship chain you would like included in this request, for convenience in this case. Sparse fieldsets is used to reduce the data sent for any of those types to the bare minimum of requested items + linkage.


#5

Awesome. Excellent help, as always. Thank you very much :slight_smile:


#6

It looks like I missed a point in the spec requiring full linkage to be maintained except in the case of sparse fieldsets. The rest of my post still applies, but I would amend it to say that querying would require the minimum of full linkage + sparse fieldset requested content, however the returned document itself does not require full linkage in this case. In that way you are free to include or exclude the linking minimal resource objects when building the complete document for the consumer.