Home > Mobile >  REST: query string to query resource by it's array property
REST: query string to query resource by it's array property

Time:09-17

Sorry upfront if this is duplicate, but I was unable to find topic with answers to my questions.

I'm building an MEAN stack app, and I'm planning to create REST API on backend. Now I've stumbled on the following problem.

I have one resource /discussion, which contains list of users and posts itself. The resource roughly looks like this:

discussion = {
    "name": "discussionName",
    "users": [<arrayOfUsersThatArePartOfThisDiscussion>],
    "posts": [<arrayOfPostsForThisDiscussion>]
}

What I want to achieve is list all the discussions that user contributed to, so that I can present those to him. Now, what I don't understand is what is the most REST-full way to do this.

My thinking is:

  1. Maintain a list of discussions for the user. In that case, the user resource would roughly look like:

     user = {
       "id": "myId",
       "name": "MyName",
       "discussionIds": [<listOfDiscussionsImPartOf>]
     }
    

If this is my representation, what happens when user tries to post into discussion that he previously didn't post? My understanding is than in that case the POST /disucssions/:id/posts should be executed to create another post.

But then, who is updating user/:userId/discussionIds? Is that client or server duty? If it's server duty, how do I force cache invalidation for that resource (user/:userId/discussions)? so that I get fresh data on following GET user/:userId/discussions

  1. Don't maintain a list of discussions in user resource.

In this case, how do I filter discussions that user is part of? I was thinking of using query string with GET operation, but then again, how do I write query that will filter resource based on existence of provided param in it's array? For clarity purposes, I'm looking for something like:

GET api.something.com/discussions?where userId in discussion.usersIds

Hope you can answer my questions. Thanks in advance

CodePudding user response:

Maintain a list of discussions for the user.

Yup, that's fine.

what happens when user tries to post into discussion that he previously didn't post? My understanding is than in that case the POST /disucssions/:id/posts should be executed to create another post.

That's a choice that you get to make.

Think about how we do this sort of thing on the web. You want to send a question to stack overflow, so you load a form, and you type a bunch of information into that form, and you submit it. The outcome is that the web browser sends a POST request, and the request-target is...?

Well, on the web it's whatever target stack overflow put into the metadata of the form itself. You the user don't care where it goes, you just push the button. The browser doesn't care either - it just copies the meta data from the form into the HTTP request. So the authority that controls the form also gets to choose which resource should be the target.

So you could, if you wanted to, have all the forms get submitted to the same resource. Or you could have a separate resource for each kind of form. Or a separate resource for each kind of form for each web page.

But the really interesting option is to identify the most important web page that will be changed if the form submission is handled correctly, because HTTP has cache-invalidation rules that will prevent compliant caches from re-using responses that may have been changed by your request.

Alas, when successful form processing will modify multiple resources, then you have to choose (only one request-target per request).

Of course, form submission is just an example case: all unsafe requests (POST/PUT/PATCH etc) share the same cache-invalidation rules.

how do I write query that will filter resource based on existence of provided param in it's array?

You don't filter resources; you GET a resource whose representation is the list filtered by the constraint you want.

/user-discussions?userId=12345

That's a perfectly fine identifier for a resource with a representation that is a list of discussions relevant to user 12345. How it is that you obtain that representation is an implementation detail - the web doesn't care.

A common example would be to extract the userId from the query string and then to use it as a parameter in a prepared statement.

There's nothing magic about using a query string (although it is convenient on the web, because we can use forms to allow the user to provide a userId value); making the id part of the path would also be fine.

URI design (specifically, the origin-form of the URI) is about identifying the people who care about the spelling of your identifiers, and making trade offs among their different concerns (the concerns of the writers producing your documentation aren't quite the same as your operators who are reading web logs, and those aren't quite the same as customers reading through their browser history, and so on).

  • Related