简体   繁体   English

MongoDB / Mongoose搜索和创建特定的子文档

[英]MongoDB/Mongoose search and create of specific sub documents

I'm building a REST API in nodejs/express/mongodb/mongoose. 我正在nodejs / express / mongodb / mongoose中构建REST API。 I've started using MongoDB/Mongoose recently and I still have some doubts. 我最近开始使用MongoDB / Mongoose,但仍然有一些疑问。

What I'm trying to achieve is to access a specific user bag (a user can have multiple bags) and also I want to be able to add to that bags participants/payers. 我想要实现的目的是访问特定的用户包(一个用户可以有多个包),而且我希望能够将参与者/付款人添加到该包中。 (a user bag can have multiple participants/payers) (一个用户包可以有多个参与者/付款人)

My mongoose user modal contains the rest of the schemas. 我的猫鼬用户模态包含其余的模式。 I created a schema for each one because I believe it would be easier to find a given bag or participant directly because of the ObjectId (not sure if this is correct). 我为每个人创建了一个架构,因为我相信由于ObjectId(不确定这是否正确),直接找到给定的书包或参与者会更容易。

Mongoose Modal/Schemas: 猫鼬模态/模式:

const PayerSchema = new Schema({
  name: {
    type: String
  },
  amount: {
    type: Number
  }
});

const BagSchema = new Schema({
  name: {
    type: String
  },
  type: {
    type: String
  },
  payers: [PayerSchema]
});

const UserSchema = new Schema({
  name: {
    type: String,
    required: [true, 'User name field is required']
  },
  bags: [BagSchema]
});

module.exports = mongoose.model('User', UserSchema);

I was able to create the CRUD controller methods for a new user, but I still not sure on: 我能够为新用户创建CRUD控制器方法,但是我仍然不确定:

  1. Creating a new bag for a specific user (I was able to do this but not sure if it's the right way) 为特定用户创建一个新手袋(我能够做到这一点,但是不确定这是否正确)
  2. Creating a new participant in a specific bag for a specific user. 在特定袋子中为特定用户创建新参与者。 (addPayer method is wrong need help here) (addPayer方法错误,需要在这里帮助)

Check out my controller user/bags/participants methods: 查看我的控制器用户/袋/参与者方法:

const User = require('../models/userModel');

getAllUserBags: (req, res, next) => {
    User.findById({ _id: req.params.id }).then((user) => {
      res.send(user.bags);
    })
    .catch(next);
  },
  getOneUserBag: (req, res, next) => {
    console.log(req.params.bagid);
    User.find({ 'bags._id': req.params.bagid}, {"bags.$" : 1}).then((obj) => {
      res.send(obj);
    })
    .catch(next);
  },
  createBag: (req, res, next) => {
    let bag = req.body.bag;
    User.findOneAndUpdate(
      {_id: req.body.id},
      {$push: {bags: bag}
    }).then(() => {
      //Unnecessary - just to return update user with new bag.
      User.findOne({_id: req.body.id}).then((user) => {
        res.send(user);
      })
    }).catch(next);
  },
  addPayer: (req, res, next) => {
    let payer = req.body.payer;
    User.find(
      {'bags._id': req.params.bagid},
      {"bags.$" : 1},
      {$push: {payers: payer}
    }).then((obj) => {
      console.log(obj);
      //Unnecessary - just to return update user with new bag.
      // User.findOne({_id: req.body.id}).then((user) => {
      //   res.send(user);
      // })
    }).catch(next);
  } 

Thanks for the help 谢谢您的帮助

Base on what we discuss, your User schema is good enough for your requirements, as long as making sure that one User document does not exceed the 16MB limit of MongoDB document. 根据我们的讨论,只要确保一个User文档不超过MongoDB文档的16MB限制,您的User模式就足以满足您的要求。


Creating a new bag for a specific user (I was able to do this but not sure if it's the right way) 为特定用户创建一个新手袋(我能够做到这一点,但是不确定这是否正确)

Yours is fine. 没事的 However, there are some improvements: 但是,有一些改进:

createBag: (req, res, next) => {
  User.findByIdAndUpdate(req.body.id, {
      $push: { bags: req.body.bag }
    }, {
      new: true // this will make the query getting the updated document
    })
    .then(user => {
      res.json(user);
    })
    .catch(next);
})

Creating a new participant in a specific bag for a specific user. 在特定袋子中为特定用户创建新参与者。 (addPayer method is wrong need help here) (addPayer方法错误,需要在这里帮助)

Since you decided to nest the 'bags', the bag.id might be duplicated among User documents. 由于您决定嵌套“袋子”,因此bag.id可能会在User文档中重复。 See this to understand the possibility. 看到以了解可能性。 Thus, I recommend using an userId along with bagId : 因此,我建议将userIdbagId一起使用:

getOneUserBag: (req, res, next) => {
  User.findOne({
      _id: req.params.userId,
      bags._id: req.params.bagId
    })
    .then(user => {
      if (!user) res.status(404).end();

      let bag = user.bags.id(req.params.bagId);

      res.json(bag);
    })
    .catch(next);
}

addPayer: (req, res, next) => {
  User.findOneAndUpdate({
      _id: req.params.userId,
      bags: $elemMatch: {
        _id: req.params.bagId
      }
    }, {
      $push: { 'bags.$.payers': req.body.payer } // Use 'positional $' operator along with $elemMatch in the query to update only the matched bag
    }, {
      new: true // Do not forget the 'new' options to get the updated document
    })
    .then(user => {
      if (!user) res.status(404).end();

      res.json(user);
    })
    .catch(next);
}

and in the router 并在路由器中

router.get('/users/:userId/bags/:bagId', getOneUserBag);
router.post('/users/:userId/bags/:bagId/payers', addPayer);

In the getAllUserBags() , you use the wrong syntax for User.findById() : getAllUserBags()您使用了错误的语法User.findById()

getAllUserBags: (req, res, next) => {
  User.findById(req.params.id) // Not { _id: req.params.id }
    .then((user) => {
      res.json(user.bags);
    })
    .catch(next);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM