sql >> データベース >  >> NoSQL >> MongoDB

Mongoose&Express:参照データを適切に削除、作成、保存する方法

    スキーマをより簡単な方法で再設計する必要があると思います。モデル間の参照が多すぎるため、問題が発生します。たとえば、コメントを作成する場合は5 dbアクセス、作成する場合は6dbアクセスがあります。コメントを削除します。

    投稿とコメント参照を削除してこのようなユーザースキーマを作成しますが、後でユーザーからの投稿にアクセスするときに、仮想入力

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

    また、投稿スキーマで、コメント参照を削除しました(簡単にするために、好きなフィールドと嫌いなフィールドを削除しました)。

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

    コメントスキーマはそのままにしておくことができます。

    投稿にコメントを追加するには、2つのdbアクセスのみが必要です。1つは投稿が存在するかどうかを確認するためのもので、もう1つは投稿を作成するためのものです。

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

    次の2人のユーザーがいるとしましょう:

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

    _id:"5e216d74e7138b638cac040d"のUser1 この投稿があります。

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

    _id:"5e217192d204a26834d013e8"のuser2としましょう この投稿に次のように2回コメントしました:

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

    コメントを削除するには、次のルートを使用できます。ご覧のとおり、dbアクセスを6から3に減らし、コードはより短く、よりクリーンになっています。

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

    今、あなたは尋ねるかもしれません、ユーザーからの投稿にどのようにアクセスしますか?ユーザースキーマに仮想入力を設定しているため、次のように投稿に入力できます。

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


    1. マングースですべてをクエリして合計します

    2. 配列に埋め込まれたドキュメントを返すMongodbselectフィールド

    3. MongoDB Javaドライバーの集約パイプライン実行でタイムアウトを設定する動作は何ですか?

    4. RedisとMongoDB