How do relational databases work with a REST API? - rest

I'm trying to understand how a REST API would work when dealing with a relational, normalized database. For example, given the tables Customer, Order, and OrderType:
Customer
ID
Name
Address
Order
ID
Amount
TypeId
CustomerId
Order Type
ID
Desc
If I wanted to lookup all the order information for a given customer, I would do something like url/customers/:customerId/orders; and in the the API it would handle performing joins on tables in order to return a response like this?
{
"orderNumber": 123,
"type": "online",
"customer": "john doe",
"amount": "500"
},
{
"orderNumber": 124,
"type": "in-store",
"customer": "jane doe",
"amount": "100"
}
Is that correct? Or would I need to do separate API calls such as url/customers/:customerId, url/orders/:customerId, and url/orderType/:typeId then assemble the information in the front end?

If you assemble information on front end you lose most benefits of relational database and have to write lots of code instead of one line of sql. You design your API routes according to specific tasks you want to perform, which does not depend on application architecture and what stack of technologies you use.

Related

REST API: How to fetch objects and popular objects, should it be same API or separate API?

We have several API endpoints like:
/api/cities/ => Fetches all cities in our database. Its an oversimplified example, actually we have around 1k cities.
{
"name": "Chicago",
"name": "Los Angeles",
"name": "New York",
"name": "Phoenix"
}
Currently these API returns city list in alphabetic order.
We have new requirement where we need to fetch popular cities at the top, this followed by list in alphabetic order.
JSON Output would look like:
{
"popular"
{
"name": "New York",
"name": "Los Angeles"
},
"all"
{
"name": "Chicago",
"name": "Los Angeles",
"name": "New York",
"name": "Phoenix"
}
}
How should current APIs be modified to fulfil this:
Should we create new API like /api/popularcities/ which would fetch list of popular cities? This way client would call /api/popularcities/ first and then /api/cities/ API.
Should we add query string parameter in existing API /api/cities/?fetch=popularall to fetch both popular and all cities.
Or any other thing, this doesn't look like filter attribute as this is actually adding result at the top and not filtering it out.
We do need to repeat popular cities in all city list as this would be binded directly to UI dropdown and requirement is to keep alphabetic ordering intact.
Suggestions?
popular cities are a way of sorting for the same entities.
It shouldn't be a new resource, but a way of querying the same resource sorted differently to get the needed entries.
I would use a query for that: ?sort=popular.
you can use both endpoint, a endpoint like as shortcut of api fetch all with order by popular.
/cities?sort=popular
/popular_cities

"Right" REST URL to get all resources within all resources?

So... I am aware that this question could be dangerously close to being opinion based . I'm hoping is not, and that the REST standard is clear about what I'm going to ask but if it's not, I'll close it.
I have a website (in Django, with the data being stored in Postgres) with Product(-s) and Category(-ies) Each category can contain several product(-s).
So, the question is: What would be the "right" endpoint (if there's any) to GET all the categories with all the products in each?
I believe it would be clear getting all the products of a specific category. For instance, if the category ID was 24, in order to get all its products, I would write:
http://myserver.com/api/categories/24/products
But how about ALL the categories with ALL the products in each?
Would it be http://myserver.com/api/categories/products?
Would it be http://myserver.com/api/categories/all/products?
Would it be better using some kind of parameter, such as http://myserver.com/api/categories?mode=all_products ?
The idea would be having a response like this (JSON format)
{
"25": [{
"id": 1,
"name": "Product 1 in category 25",
"price": 100
}, {
"id": 2,
"name": "Product 2 in category 25",
"price": 200
}],
"26": [{
"id": 3,
"name": "Product 1 in category 26",
"price": 300
}, {
"id": 4,
"name": "Product 2 in category 26",
"price": 400
}]
}
Thank you in advance.
As far as REST is concerned if you are uniquely representing the resource in the url so that it is cacheable (and abiding with HATEOAS but let's skip that part), it doesn't really matter how you structure your urls. With that said in my opinion, since you want to get all the products, your url should be something like
GET /products # to return all products with their associated categories
GET /category/24/products # to return all products belonging to a particular category
Note:- Although url structure is not exactly a part of REST, but designing url in terms of an entity/resource and an identifier does makes it easier to create RESTful APIs. Well structured urls also makes them easier to be consumed by clients.

Best way to represent multilingual database on mongodb

I have a MySQL database to support a multilingual website where the data is represented as the following:
table1
id
is_active
created
table1_lang
table1_id
name
surname
address
What's the best way to achieve the same on mongo database?
You can either design a schema where you can reference or embed documents. Let's look at the first option of embedded documents. With you above application, you might store the information in a document as follows:
// db.table1 schema
{
"_id": 3, // table1_id
"is_active": true,
"created": ISODate("2015-04-07T16:00:30.798Z"),
"lang": [
{
"name": "foo",
"surname": "bar",
"address": "xxx"
},
{
"name": "abc",
"surname": "def",
"address": "xyz"
}
]
}
In the example schema above, you would have essentially embedded the table1_lang information within the main table1document. This design has its merits, one of them being data locality. Since MongoDB stores data contiguously on disk, putting all the data you need in one document ensures that the spinning disks will take less time to seek to a particular location on the disk. If your application frequently accesses table1 information along with the table1_lang data then you'll almost certainly want to go the embedded route. The other advantage with embedded documents is the atomicity and isolation in writing data. To illustrate this, say you want to remove a document which has a lang key "name" with value "foo", this can be done with one single (atomic) operation:
db.table.remove({"lang.name": "foo"});
For more details on data modelling in MongoDB, please read the docs Data Modeling Introduction, specifically Model One-to-Many Relationships with Embedded Documents
The other design option is referencing documents where you follow a normalized schema. For example:
// db.table1 schema
{
"_id": 3
"is_active": true
"created": ISODate("2015-04-07T16:00:30.798Z")
}
// db.table1_lang schema
/*
1
*/
{
"_id": 1,
"table1_id": 3,
"name": "foo",
"surname": "bar",
"address": "xxx"
}
/*
2
*/
{
"_id": 2,
"table1_id": 3,
"name": "abc",
"surname": "def",
"address": "xyz"
}
The above approach gives increased flexibility in performing queries. For instance, to retrieve all child table1_lang documents for the main parent entity table1 with id 3 will be straightforward, simply create a query against the collection table1_lang:
db.table1_lang.find({"table1_id": 3});
The above normalized schema using document reference approach also has an advantage when you have one-to-many relationships with very unpredictable arity. If you have hundreds or thousands of table_lang documents per give table entity, embedding has so many setbacks in as far as spacial constraints are concerned because the larger the document, the more RAM it uses and MongoDB documents have a hard size limit of 16MB.
The general rule of thumb is that if your application's query pattern is well-known and data tends to be accessed only in one way, an embedded approach works well. If your application queries data in many ways or you unable to anticipate the data query patterns, a more normalized document referencing model will be appropriate for such case.
Ref:
MongoDB Applied Design Patterns: Practical Use Cases with the Leading NoSQL Database By Rick Copeland

Is my MongoDB data model the right choice?

I'm going to build my first project (genealogy database) with MongoDB and nodejs and I am asking myself, if my data model is the right choice:
people document (simplified):
{
"_id": ObjectId("123"),
"modified": ISODate("2015-02-04T16:52:32.601Z"),
"birth": ISODate("1995-02-04T16:52:32.601Z"),
"name": "peter"
}, {
"_id": ObjectId("456"),
"modified": ISODate("2015-02-04T16:52:32.601Z"),
"birth": ISODate("1999-02-04T16:52:32.601Z"),
"name": "uschi"
}
relations document (simplified):
{
"sourceID": ObjectId("123"),
"targetID": ObjectId("456"),
"type": "Married",
"modified": ISODate("2015-02-04T16:52:32.599Z"),
"startrelation": ISODate("2001-02-04T16:52:32.601Z"),
"endrelation": ISODate("2007-02-04T16:52:32.601Z"),
"_id": ObjectId("54d24e5033bfc203aaaad590")
}
Yesterday I tried to retrieve a list with all people and their related people and got worries about my data model because I needed a lot of code to generate the following result:
items: [
{
"_id": ObjectId("123"),
"modified": ISODate("2015-02-04T16:52:32.601Z"),
"birth": ISODate("1995-02-04T16:52:32.601Z"),
"name": "peter"
"married": [{
"_id": ObjectId("456"),
"modified": ISODate("2015-02-04T16:52:32.601Z"),
"birth": ISODate("1999-02-04T16:52:32.601Z"),
"name": "uschi"
}, ...]
}, ...]
Is there are problem with that solution?
The main problem I see with this solution is that you are using MongoDB to store relational data. I have done this in the past and regretted it. Consider using Postgres. It's a relational db but also has a feature called hstore which allows you to store and query arbitrarily structured json if your schema has some areas that may not be well defined.
It seems that graph-database would be perfect match for you problem domain.
This way you wont have to implement all the logic related to "relations" in your application. GraphDBs natively understand them.
i.e. neo4j
Graph databases allow for
easily handle complex relations
very quick traversal of relations
fast searching for relationships of the type "friends of a friend" or who is Jim in relation to Janet
In general, if you are planning to query your data in various ways looking on relations, graph database is the way to go,

Emulating LEFT JOIN on MongoDB using MapReduce/Aggregation

I have a mongo database with few collections such as a user in the system (id, name, email) and list of projects (id, name, list of users who have access)
User
{
"_id": 1,
"name": "John",
"email": "john#domain.com"
}
{
"_id": 2,
"name": "Sam",
"email": "sam#domain.com"
}
Project
{
"_id": 1,
"name": "My Project1",
"users": [1,2]
}
{
"_id": 2,
"name": My Project2",
"users": [2]
}
In my dashboard, I display a list of projects and the names of its users. To support names - I've changed the "users" field to now also include the name:
{
"_id": 2,
"name": "My Project2",
"users": [{"_id":2,"name":"Sam"}]
}
But on several pages, I now need to also print their email address and later on - maybe also display their image.
Since I don't want to start and embed the entire User document in each project, I'm looking for a way to do a LEFT JOIN and pick the values I need from the User collection.
Performances are NOT important so much on those pages and I rather prefer an easy way to manage my data. So basically I'm looking for a way to query for a list of all projects and associated users with different fields from the original User document.
I've read about the map-reduce and aggregation option of mongo and to be honest - I'm not sure which to use and how to achieve what I'm looking for.
MongoDb doesn't support joins in any form even by using MapReduce and Aggregation Framework. Only way you could implement join between collection is in your code. So just implement LEFT JOIN logic in your code.