-1

So I am trying to make first full-stack app and I have a question related to the database and this seemed the best place to ask. So in my users need to create accounts and then they have a "cookbook" which is a list of recipes that get randomly chosen from and sent to their email weekly. What is the best way for me to associate the recipes with their respective user? I have a simple MongoDB backend built but in it, the recipes and users are saved in different places. I was thinking of linking the recipes to the user by giving the recipe its creators UUID but I also want users to be able to share their recipes and have other people add that recipe to their "cookbook". is there a way I can each user in the database an array of recipes and add the recipe to array when they create one or add someone else's or is there a better way?

here is the code for my simple mongodb backend

Recipe saving in the database

const router = require("express").Router();
let Recipe = require("../models/recipe.model");

router.route("/").get((req, res) => {
    Recipe.find()
    .then(rec => res.json(rec))
    .catch(err => res.status(400).json("Error: "+err))
})

router.route("/add").post((req, res) => {
    const name = req.body.name;
    const description = req.body.description;
    const imageLink = req.body.imageLink || "";
    const ingredients = Array.from(req.body.ingredients);
    const steps = Array.from(req.body.steps);
    const isPrivate = Boolean(req.body.private);

    const newRecipe = new Recipe({
        name,
        description,
        imageLink,
        ingredients,
        steps,
        isPrivate
    });

    newRecipe.save()
        .then(() => res.json("Recipe added"))
        .catch(err => res.status(400).json("Error: " + err))
})

router.route("/:id").get((req, res) => {
    Recipe.findById(req.params.id)
    .then(rec => res.json(rec))
    .catch(err => res.status(400).json("Error: "+err))
})

router.route("/:id").delete((req, res) => {
    Recipe.findByIdAndDelete(req.params.id)
    .then(() => res.json("Recipe Deleted"))
    .catch(err => res.status(400).json("Error: " + err))
})

router.route("/update/:id").post((req, res) => {
    Recipe.findById(req.params.id)
    .then(rec => {
        rec.name = req.body.name;
        rec.description = req.body.description;
        rec.imageLink = req.body.imageLink;
        rec.ingredients = Array.from(req.body.ingredients);
        rec.steps = Array.from(req.body.steps);
        rec.isPrivate = Boolean(req.body.isPrivate);

        rec.save()
        .then(() => res.json("Recipe updated"))
        .catch(err => res.status(400).json("Error: "+err))
    })
    .catch(err => res.status(400).json("Error: " + err))
})


module.exports = router

and saving users into the database

const router = require("express").Router()
let User = require("../models/user.model")

router.route("/").get((req, res) => {
    User.find()
      .then(users => res.json(users))
      .catch(err => res.status(400).json("Error: "+err));
});

router.route("/add").post((req, res) => {
    const username = req.body.username;
    const email = req.body.email;
    const newUser = new User({username, email})

    newUser.save()
    .then(() => res.json("User added"))
    .catch(err => res.status(400).json("Error: "+err))
})

module.exports = router
david snyder
  • 337
  • 3
  • 16
  • Why not both? Give ownership of the original recipe to the creating user using their user ID and maintain an array of IDs of "favorited" or "added" recipes for each user. They're two distinctly separate features and should likewise be handled using separate logic. For the arrays, just use `$addToSet` and `$pull` to manage the array elements to maintain atomicity of your operations. – B. Fleming Feb 04 '20 at 23:03
  • In any case, this question doesn't really have a distinct, objectively answerable problem. You're essentially asking for advice on best practices, which will generally be subjective. This question would be better suited for [CodeReview](https://codereview.stackexchange.com/). StackOverflow is more suited for asking about how to implement the specific approach you've selected. – B. Fleming Feb 04 '20 at 23:10
  • @B.Fleming you are correct that I am more asking for best practices but I am also asking how to implement those best practices. I am sorry if that wasn't clear in the original question – david snyder Feb 04 '20 at 23:26
  • I'm aware of your intent, no worries. I'm only suggesting that the most appropriate course of action is to discuss best practices on CodeReview and then, once you've determined which approach you wish to implement, discuss the implementation details here. This ensures that the scope of your questions fall within the site guidelines. – B. Fleming Feb 04 '20 at 23:32

1 Answers1

0

@david I believe the question is about embedding or referencing the recipes in User collection. In case my understanding is correct, then 'MongoDB relationships: embed or reference?' can help you and it answers the question very well.

  1. It is encouraged to embed, rather than referencing in case document size is not expected to go beyond 16 MB. Since that's what NoSql databases are meant to(Non- structured/relational data).
  2. It is rather easy to find data with-in the same collection if we embed the recipe along with user collection.
  3. If the recipe is a different collection then in case a user has a new recipe(not present in the recipe collection), then we need to add to recipe collection as well.

I suggest embedding the recipe as an array to user collection since embedding this will make it easy to query data and looking at User collection, document size will not cross the limit of 16 MB.

I hope, this helps.

Hemant Kumar
  • 186
  • 6