TLDR: need standard/framework to accomplish such a query /courses?teacher.age=30 over multiple resources (course, teacher).
We are using Spring Data Rest to expose our relational database tables in a hateoas format. The entities are published as REST resources.
Now, the users would like to search over multiple resources.
For example "give me the names of all courses given by a teacher of 30 years old".
Because we need courses, this would be a search operation on /courses.
However, the age of a teacher is on /teachers.
So in 2 steps:
/teachers?age=30 which have _links to courses. Then, every course can be opened to inspect it's name (eg: /course/942).
A more intuitive operation would be to directly call /courses?teacher.age=30.
This is what we would like to accomplish.
Of course, we can implement this by hand. But the real question is: are there already existing standards (and popular libraries) to accomplish this?
We would like to find a scalable solution, where not every attribute (to search on) has to be added manually.
This dot-notation is just a way of representing the query. It is not a requirement of a standard/library.
Characteristics of our application:
relational database (postgres)
json api
hal/hateoas
Related
I'm thinking about a REST API design. There are several tables in my database. For example Customer and Order.
Of course - each Order has its Customer (and every customer can have many Orders).
I've decided to provide such an interface
/api/v1/Customers/ -- get list of Customers, add new Customer
/api/v1/Customers/:id: -- get Customer with id=:id:
/api/v1/Orders/ -- get list of Orders, add new Order
/api/v1/Orders/:id: -- get Order with id=:id:
It works flawlessly. But my frontend has to display a list of orders with customer names. With this interface, I will have to make a single call to /api/v1/Orders/ and then another call to /api/v1/Customer/:id: for each record from the previous call. Or perform two calls to /api/v1/Orders/ and /api/v1/Customers/ and combine them on the frontend side.
It looks like overkill, this kind of operation should be done at the database level. But how can/should I provide an appropriate interface?
/api/v1/OrdersWithCustomers
/api/v1/OrdersWithCustomers/:id:
Seems weir. Is it a right way to go
There's no rule that says you cannot "extend" the data being returned from a REST API call. So instead of returning "just" the Order entity (as stored in the backend), you could of course return an OrderResponseDTO which includes all (revelant) fields of the Order entity - plus some from the Customer entity that might are relevant in your use case.
The data model for your REST API does not have to be an exact 1:1 match to your underlying database schema - it does give you the freedom to leave out some fields, or add some additional information that the consumers of your API will find helpful.
Great question, and any API design will tend to hit pragmatic reality at some point like this.
One option is to include a larger object graph for each resource (ie include the customer linked to each order) but use filter query parameters to allow users to specify what properties they require or don't require.
Personally I think that request parameters on a restful GET are fine for either search semantics when retrieving a list of resources, or filtering what is presented for each resource as in this case
Another option for your use case might be to look into a GraphQL approach.
How would you do it on the web?
You've got a web site, and that website serves documents about Customers, and documents about Orders. But your clients aren't happy, because its too much boring, mistake-prone work to aggregate information in the two kinds of documents.
Can we please have a document, they ask, with the boring work already done?
And so you generate a bunch of these new reports, and stick them on your web server, and create links to make it easier to navigate between related documents. TA-DA.
A "REST-API" is a facade that makes your information look and act like a web site. The fact that you are generating your representations from a database is an implementation details, deliberately hidden behind the "uniform interface".
I've built a RESTful API that fetches employees from the database, Now I want to implement search functionality that filters employees by name and then fetches it. In the frontend, I've fetched employees and then based on user input I'm converting both user input and result from db to lowercase and then matching for similarity? Do you think this problem can be approached in a different way? any other strategies? thanks
Yes, let the database do the comparison for you in SQL. Less resources will be used throughout the entire stack. One of the main features for databases is searching for specific data. Also SQL is case insensitive so no need to do a toLowerCase.
SELECT *
FROM Employees
WHERE name LIKE '%SearchValue%'
Only select the columns you need.
I wanted to provide functionality to clients from my service to get the data based on different fields or sometimes combination of fields. Eg.
getByA
getByB
getByC
getByAandB
getByAandC
In domain driven design, while designing the GET APIs, what should I do out of the following 2:
Should I create individual get api for all such functionalities I wanted to provide?
Should I create one get API with all the possible gets by using all these fields in query parameter. Eg.
get?A=?&B=?&C=?
Which one is the better way to do this? Any suggestions on best practice?
There is a middle path between using individual GET APIs for each of these queries and creating one GET API.
You could use the Specification pattern to expose one GET API, but translate it into a Domain Specification Object before passing it on to the Domain layer for querying. You typically do this transformation in your View Controller, before invoking the Application Service.
Martin Fowler and Eric Evans have published a great paper on using Specifications: https://martinfowler.com/apsupp/spec.pdf
As the paper states, The central idea of Specification is to separate the statement of how to match a candidate, from the candidate object that it is matched against.
Note:
You are fine if you are using this pattern for the Query side as you have outlined in your question, and avoid reusing it in different contexts. For ex., DO NOT use a specification object on both the query side and command side, if you are using (or plan to use) CQRS. You will be creating a central dependency between two parts, that NEED to be kept separate.
Specifications are handy when you want to represent a domain concept. Evaluate your queries (getByAandB and getByAandC) to draw out the question you are asking to the domain (For ex., ask your domain expert to describe the data he is trying to fetch).
so I'm working with a database that has multiple collections and some of the data overlaps in the collection . In particular I have a collection called app-launches which contains a field called userId and one called users where the _id of a particular object is actually the same as the userId in app-launches. Is it possible to group the two collections together so I can analyze the data? Or maybe match the the userId in app-launches with the _id in users?
There is no definit answer for your question Jeffrey and none of the experts here can tell you to choose which technique over other just by having this information.
After going through various web pages over internet and mongo documentation and understanding the design patterns used in Mongo over a period of time, How I would design it depends on few things which I can try explaining it here in short.
if you have a One-To-One relation then always prefer to choose Embedding over Linking. e.g. User and its address (assuming user has only one address) thus you can utilize the atomicity (without worrying about transactions) as well easily fetch the records without too and fro to bring other information as in the case of Linking (like in DBRef)
If you have One-To-Many relation then you need to consider whether you can do the stuff by using Embedding (prefer this as explained the benefits in point 1). However, embedding would help you if you always want the information altogether e.g. Post/Comments where your requirement is to get the post and all of its comments by postId let say. But think of a situation where you need to get all the comments (and it related posts) which contains some specific tags in comments. in this case you should prefer Linking Because if you go via Embedding route then you would end up getting all the collection of comments for a post and you have to filter the desired comments.
for a Many-To-Many relations I would prefer two separate entities as well another collection for linking them e.g. Product-Category.
-$
I 'm really having a hard time with the RESTful paradigm + nested urls. I have asked a question that lead me to where I am right now here. My Domain is roughly this: there are schools, courses of a school and teachers of schools. Now schools, courses and teacher are not "nested" entities in the sense that you can refer to any of them with one Id. The site is a collection of "micro-sites" for each school showing each one's courses and teachers. A course or teacher can only exist in one school.
say we have a url like /schools/1/courses/10 . Course 10 of school 1. This works fine. Say that the user changes by hand 10 into 11, which happens to exist but is a course of school 2. Right now that leads to a mess, my site still "thinks" the user is in school 1 but shows course 3 as part of it.
Should I make detail-actions parametric to both the Id being asked for AND the "parent" entity (the school in this case) that it involved? Fetch from repositories not only by id but with a school constraint?
Or is there any better way to do this?
The way I would think about it is this; even though there may be a course 11 in your service, there is no resource that exists at the URI /schools/1/courses/11. Since there is no resource at this URI, I would return an HTTP 404 response to requests for the URI.
One way you may improve your service would be to replace the integer ID values with the names of the entities (this would require the names be unique). This would make your URIs more user friendly. An example would be /schools/Hogwarts/courses/Potions.
To further improve your service, you'll want to give users a way to navigate through the service to all of the different resources available. For example you'll probably want to allow them get a list of all courses offered by a certain school. To do that you'd expose a resource at /schools/Hogwarts/courses/ whose return type would be a list of all courses offered by the school. The representation of this list could be an XML document like the following snippet:
<courses>
<course uri="/schools/hogwarts/courses/defense+against+the+dark+arts">Defense against the dark arts</course>
<course uri="/schools/hogwarts/courses/potions">Potions</course>
</courses>
Should I make detail-actions
parametric to both the Id being asked
for AND the "parent" entity (the
school in this case) that it involved?
Fetch from repositories not only by id
but with a school constraint?
Yes.
Or is there any better way to do this?
Nothing wrong with what you described above.
You could do it with a catch-all route, and then parsing the url elements yourself.