It's a general design question about the design of RESTful routes for related/nested resources at the example of ExpressJS with MongoDB. In summary, how should I design such nested/linked routes?
About my application/scenario: I've a RESTful service implemented with NodeJS/ExpressJS and MongoDB. I've two different related models Category
and Article
.
const mongoose = require('mongoose');
const article = new mongoose.Schema({
title: {
type: String,
required: true
},
body: {
type: String,
required: true
},
category: {
type: mongoose.Types.ObjectId,
ref: 'Category',
required: true
}
});
const category = new mongoose.Schema({
name: {
type: String,
required: true
}
});
I found two ways to design the relation ship respectively the routes:
Relationship oriented
This means nested paths are used and the relationship is straight forward /api/categories/:category/articles/:article
.
The advantage is that's super easy to set the article's category because it's possible to preload it by the identifier path param (:category) with express middleware.
router.post('/', (request, response, next) => {
let article = new Article(request.body);
article.category = request.category; // Preloaded category
...
});
The disadvantage is that's really hard to get all articles by oen specific user because with that design you get only all articles for one category. For Example /api/categories/1/articles
you get only articles for the first category so if you filter with queries for examle ?user=5
you will find only the articles of user 5 for category 1 but not all of user 5's articles.
Accessibility oriented
This means no deep nested routes and separate "endpoint's" for each resource /api/categories/:category
AND /api/articles/:article
.
The advantage is that's now super easy to filter by the highly diverse properties and condiftions like ?user=5
or ?title=Works
.
A big disadvantage is now that I can't just use the path params identifier for a category because it doesn't exist. The means the user must specify inside of the request body the category. Are there best practices to implement this?
Which design would you prefer and are there any best practices for dealing with the disadvantage?
EDIT
I forgot the specify that I found this article but it doesn't seem to deal with the mentioned disadvantages. I'm highly interested in approachs to deal with them.