sql >> Databáze >  >> NoSQL >> MongoDB

Mongoose &Express:Jak správně odstranit, vytvořit a uložit data, která jsou referenční

Myslím, že musíte svá schémata přepracovat jednodušším způsobem, mezi modely je příliš mnoho referencí a to způsobuje problémy, například máte 5 db přístup, když chcete vytvořit komentář, a 6 db přístup, když chcete smazat komentář.

Vytvořil bych uživatelské schéma jako toto odstraněním příspěvků a odkazů na komentáře, ale později, když chceme mít přístup k příspěvkům od uživatelů, nastavil jsem virtuální populace.

const UserSchema = new Schema(
  {
    name: {
      type: String,
      required: true
    },
    email: {
      type: String,
      required: true,
      unique: true
    },
    password: {
      type: String,
      required: true
    },
    avatar: {
      type: String
    },
    date: {
      type: Date,
      default: Date.now
    }
  },
  {
    toJSON: { virtuals: true }
  }
);

UserSchema.virtual("posts", {
  ref: "Post",
  localField: "_id",
  foreignField: "user"
});

A ve schématu příspěvků jsem odstranil odkazy na komentáře. (Pro zjednodušení jsem odstranil pole Líbí se a Nelíbí se.)

const PostSchema = new Schema(
  {
    user: {
      type: Schema.Types.ObjectId,
      ref: "User"
    },
    text: {
      type: String,
      required: true
    },
    date: {
      type: Date,
      default: Date.now
    }
  },
  {
    toJSON: { virtuals: true }
  }
);

PostSchema.virtual("comments", {
  ref: "Comment",
  localField: "_id",
  foreignField: "post"
});

Schéma komentářů může zůstat tak, jak je.

Nyní k přidání komentáře k příspěvku potřebujeme pouze 2 db přístup, jeden pro kontrolu, zda příspěvek existuje, a jeden pro vytvoření příspěvku.

router.post(
  "/comment/:id",
  [
    auth,
    [
      check("text", "Text is required")
        .not()
        .isEmpty()
    ]
  ],
  async (req, res) => {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      return res.status(400).json({ errors: errors.array() });
    }

    try {
      const post = await Post.findById(req.params.id);
      if (!post) {
        return res.status(404).json({ msg: "Post not found" });
      }

      let comment = new Comment({
        text: req.body.text,
        post: req.params.id,
        user: req.user.id
      });

      comment = await comment.save();

      res.json(comment);
    } catch (err) {
      console.error(err.message);
      res.status(500).send("Server Error");
    }
  }
);

Řekněme, že máme tyto 2 uživatele:

{
    "_id" : ObjectId("5e216d74e7138b638cac040d"),
    "name" : "user1"
}
{
    "_id" : ObjectId("5e217192d204a26834d013e8"),
    "name" : "user2"
}

Uživatel1 s _id:"5e216d74e7138b638cac040d" má tento příspěvek.

{
    "_id": "5e2170e7d204a26834d013e6",
    "user": "5e216d74e7138b638cac040d",
    "text": "Post 1",
    "date": "2020-01-17T08:31:35.699Z",
    "__v": 0,
    "id": "5e2170e7d204a26834d013e6"
}

Řekněme uživatel2 s _id:"5e217192d204a26834d013e8" okomentoval tento příspěvek dvakrát takto:

{
    "_id" : ObjectId("5e2172a4957c02689c9840d6"),
    "text" : "User2 commented on user1 post1",
    "post" : ObjectId("5e2170e7d204a26834d013e6"),
    "user" : ObjectId("5e217192d204a26834d013e8"),
    "date" : ISODate("2020-01-17T11:39:00.396+03:00"),
    "__v" : 0
},
{
    "_id": "5e21730d468bbb7ce8060ace",
    "text": "User2 commented again on user1 post1",
    "post": "5e2170e7d204a26834d013e6",
    "user": "5e217192d204a26834d013e8",
    "date": "2020-01-17T08:40:45.997Z",
    "__v": 0
}

K odstranění komentáře můžeme použít následující cestu, jak vidíte, snížili jsme přístup k databázi z 6 na 3 a kód je kratší a čistší.

router.delete("/comment/:id/:comment_id", auth, async (req, res) => {
  try {
    const comment = await Comment.findById(req.params.comment_id);

    if (!comment) {
      return res.status(404).json({ msg: "Post do not have this comment" });
    }

    if (comment.user.toString() !== req.user.id) {
      return res.status(401).json({ msg: "User not authorized" });
    }

    await comment.remove();

    // resend the comments that belongs to that post
    const postComments = await Comment.find({ post: req.params.id });
    res.json(postComments);
  } catch (err) {
    console.error(err.message);
    res.status(500).send("Server Error");
  }
});

Nyní se můžete ptát, jak bude mít uživatel přístup k příspěvkům? Protože v našem uživatelském schématu nastavujeme virtuální vyplnění, můžeme příspěvky naplnit takto:

router.get("/users/:id/posts", async (req, res) => {
  const result = await User.findById(req.params.id).populate("posts");

  res.send(result);
});


  1. Jak vypočítám vzdálenost trasy mezi mnoha body GeoJSON v MongoDB?

  2. Jak najít všechny sbírky od mongoose

  3. Aktualizujte dokument pomocí výsledku zřetězených polí

  4. Nastavení MongoDB s node.js:Chyba:Nepodařilo se připojit k [localhost:27017]