MongoDB
 sql >> Baza danych >  >> NoSQL >> MongoDB

Mongoose &Express:Jak prawidłowo usuwać, tworzyć i przechowywać dane, które są odniesieniami?

Myślę, że musisz przeprojektować swoje schematy w prostszy sposób, jest zbyt wiele odniesień między modelami, co powoduje problemy, na przykład masz dostęp 5 db, gdy chcesz utworzyć komentarz, i dostęp 6 db, gdy chcesz usuń komentarz.

Stworzyłbym schemat użytkownika w ten sposób, usuwając odniesienia do postów i komentarzy, ale później, gdy chcemy uzyskać dostęp do postów użytkowników, ustawiłem wypełnianie wirtualne

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 w schemacie postów usunąłem odniesienia do komentarzy. (Dla uproszczenia usunąłem pola lubię i nie lubię.)

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"
});

Schemat komentarzy może pozostać bez zmian.

Teraz, aby dodać komentarz do posta, potrzebujemy tylko 2 db dostępu, jednego do sprawdzenia, czy post istnieje, a drugiego do jego utworzenia.

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");
    }
  }
);

Załóżmy, że mamy tych 2 użytkowników:

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

Użytkownik1 z _id:"5e216d74e7138b638cac040d" ma tego posta.

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

Załóżmy, że użytkownik2 z _id:"5e217192d204a26834d013e8" skomentował ten post dwa razy w ten sposób:

{
    "_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
}

Aby usunąć komentarz, możemy użyć następującej ścieżki, jak widać, zmniejszyliśmy dostęp do bazy danych z 6 do 3, a kod jest krótszy i czystszy.

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");
  }
});

Teraz możesz zapytać, w jaki sposób uzyska dostęp do postów od użytkownika? Ponieważ konfigurujemy wirtualne wypełnianie w naszym schemacie użytkownika, możemy wypełniać posty w następujący sposób:

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

  res.send(result);
});


  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Wstawiaj wartości do tablicy bazy danych mongodb przez linię wodną (sails js)

  2. PyMongo/Mongoengine odpowiednik mongodump

  3. Tworzenie nowych kolekcji Meteor w locie

  4. Utrzymywanie kolejności żądań http w pętli for w javascript

  5. Zapytanie MongoDb, aby uzyskać maksymalne pole wewnątrz tablicy