Closed shannon closed 9 years ago
When you add a project and set its group, you're creating a new document for the project and storing the id of the related group directly on that document. Doing that doesn't modify the document for the group at all, which is why Group.projects
always stays empty. This is just a function of how mongo works than anything in the JSON API spec.
If you want creating a project to also update the document for the related group, you need to use a mongoose middleware to do so. And that will give you the ids on both sides exactly as you want.
However, I should say that it's often more trouble than it's worth (perhaps in mongoose in particular) to keep a relationship in sync on both sides. For example, you'll actually need one middleware on each model if you want the relationship to be updatable from both sides. And you may need both query middleware and document middleware, depending on your app. Therefore, you might want to think about storing the group just on the Project schema. Then, when you need all the projects for a group, you query all projects where group == desired group. That's a query that your clients could make (with a separate API request) or its one you could make for them if (in the beforeRender
for group) you're willing to have the relationship only be updatable on the project side.
Thanks @ethanresnick
Yea that's kind of what I figured. I don't really want the double link. However what I'm trying to wrap my head around is how to make the relationship discoverable through the groups resource. Trying to follow the HATEOAS principle, which I'm also new to. If I don't configure it with child array then the group resource has no evidence that there is even a project resource to query. Even if there was a way to have a relationship url that just has /projects?filter[simple][group]={id}
I would be fine with that. I'm not sure how to do that with json-api though.
Sorry I guess what I'm asking for is, is there a way to define a relationship that isn't based on the mongoose model? I want to explicitly say groups have a one to many relationship with projects.
Trying to follow the HATEOAS principe, which I'm also new to. If I don't configure it with child array then the group resource has no evidence that there is even a project resource to query.
Ok, that makes sense, and it's certainly something that JSON API (the specification) supports. You'd just respond with:
// example of a group resource object
{
"type": "groups",
"id": "2",
"relationships": {
"projects": {
"related": "/projects?filter[simple][group]=2"
}
},
"attributes": { /* ... */ }
}
By using the related
link, the client knows that there's a relationship and how to fetch the linked resources. The key is that "data"
isn't included, so the server doesn't need to know the linked ids upfront.
Now, the question is how to generate the above output with this library. Part of the answer is to add a relationship in the beforeRender
function that's part of the group's resource description, like so:
beforeRender: function(resource) {
resource.relationships.projects = new RelationshipOject(undefined, /* url template for related projects here */);
return resource;
}
where RelationshipObject
is an instance of this type. That way, you can have the relationship returned in the representation without actually having it on your model.
Then, the question is just whether the library is able to serialize that relationship without the data
key (the inclusion of which with null
or an []
would mislead clients into thinking the relationship was empty). I think the answer is currently "no" (having data
is always assumed), but that should be easy to fix.
I'm off to bed now, but I'll look at this (and the Koa strategy comments) again when I wake up. I'd happily accept a PR for this issue though. All it would have to do, I think, is tell the Documentation serializer not to output data
when the Relationship's linkage is undefined.
This should be fixed now, such that adding the relationship in beforeRender
(with undefined
linkage and an appropriate template) is all you should need to do. (Note though that I've renamed RelationshipObject
to simply Relationship
.)
Let me know if this works for you!
Yea this works great now. Thanks!
I'm trying to set up a basic one to many relationship between Groups and Projects.
Like this:
The problem is, I don't think the relationship works correctly unless I add in an array of children to the group schema like so:
If I don't add this when I call
/groups/{id}/relationships/projects
I get a404 Invalid relationship name
message.But then if I do add it, when I create a new project via
POST /projects
(specifying the group relationship correctly, I double checked) it doesn't add it to that array so then/groups/{id}/relationships/projects
is always empty.Is there something I am missing? I'm new to jsonapi so I may just be looking at this from the wrong angle.