JBCP
JBCP

Reputation: 13485

Spring Data Rest: How to search by another object's key?

In Spring-Data-Rest an object's ID is the URI returned with the object. For example, if I have a User, it might have a URI like:

http://example.com/users/1

In an authentic REST api, this URI is the id of the object, you are not supposed to use just '1' as the id.

Give that, how do I search for all Orders that belong to that User?

http://example.com/orders/search/findByUser?user={{XXX}}

Specifically, what do I use for {{XXX}}?

I know I could do the opposite search:

http://example.com/users/1/orders

But in my case I need to search for matching jobs so I can add additional parameters which are also keys.

I can export /orders/search/findByUser by creating this function definition on OrderRepository:

List findByUser(User user);

and findByUser will be exported by Spring-Data-REST, but how do I specify the User as a GET parameter?

Again, I'm specifically looking for the pure REST solution, since the Spring Data Rest project is trying to encourage purity.

Upvotes: 4

Views: 6907

Answers (3)

JR Utily
JR Utily

Reputation: 1852

See https://jira.spring.io/browse/DATAREST-502

Depending of your version of Spring Data, it would work as you want or not. By the way, I still think the POST should be an option too, it would be much cleaner.

Upvotes: 0

Thomas Eizinger
Thomas Eizinger

Reputation: 1462

You might take a look at the Query annotation of Spring Data. It enables you to execute custom queries without the need of a custom controller.

Edit:

Query parameters are a good way to filter a resource by simple properties. As SDR serializes all complex types as relations, it is even clearer that filtering only applies to the remaining (simple) properties. If you have only one relation, you correctly mentioned the way of doing the 'inverse' search as you called it by using /users/1/orders.
If you want to search by multiple relations I suggest you define a seperate search (sub-)resource and perform the search by issuing a POST-request to this resource.
For example:

POST /orders/search
{
    "user": "http://example.org/users/1",
    ...
}

This way, SDR will correctly translate the URIs into entities. However, I think you will need to use a custom controller here but it should be possible to still use the Spring Data repository and provide the user and additional entities as parameter.

For further information, see the following SO-questions:

How to design RESTful search/filtering?
RESTful URL design for search

Edit2:

Addressing the point that using a POST for searching violates the REST spec:

REST was designed to be simple. One of the key advantages of REST is that you are not forced to do anything. You can adapt the spec until it fits your needs. Of course, this could mean that your API is less RESTful but you should consider if it is worth it to strictly stick to the spec if it introduces an unnecessary overhead for the consumers of your API.

Of course you can design the above the idea to fully meet the REST spec. This would involve creating a seperate search entity, persisting it to the database and later retrieve the result of the search with a call to a subresource like /result or something like that. However, the question is, if it is worth it.

In your concrete example, I would just require the client to parse the ID out of the link and provide it as query parameter. If you are scaling up your application later, you could introduce a feature like named searches and apply the above mentioned solution.

Upvotes: 3

Andres
Andres

Reputation: 10727

If you use a controller, like it seems to be your case, you can pass it any parameter(s) you consider necessary. Take a look at this question:

Spring Data REST custom query integration

Upvotes: 0

Related Questions