How to check if that data already exist in the database during update (Mongoose And Express)

后端 未结 8 1838
灰色年华
灰色年华 2020-12-05 00:28

How to do validations before saving the edited data in mongoose?

For example, if sample.name already exists in the database, the user will receive a som

相关标签:
8条回答
  • 2020-12-05 00:33

    check with one query if email or phoneNumber already exists in DB

    let userDB = await UserS.findOne({ $or: [
      { email: payload.email },
      { phoneNumber: payload.phoneNumber }
    ] })
    
    if (userDB) {
      if (payload.email == userDB.email) {
        throw new BadRequest({ message: 'E-mail already exists' })
      } else if (payload.phoneNumber == userDB.phoneNumber) {
        throw new BadRequest({ message: 'phoneNumber already exists' })
      }
    }
    
    0 讨论(0)
  • 2020-12-05 00:34

    Another way to continue with the example @nfreeze used is this validation method:

    UserModel.schema.path('name').validate(function (value, res) {
        UserModel.findOne({name: value}, 'id', function(err, user) {
            if (err) return res(err);
            if (user) return res(false);
            res(true);
        });
    }, 'already exists');
    
    0 讨论(0)
  • 2020-12-05 00:35

    There is a more simpler way using the mongoose exists function

    router.post("/groups/members", async (ctx) => {
        const group_name = ctx.request.body.group_membership.group_name;
        const member_name = ctx.request.body.group_membership.group_members;
        const GroupMembership = GroupModels.GroupsMembers;
        console.log("group_name : ", group_name, "member : ", member_name);
        try {
            if (
                (await GroupMembership.exists({
                    "group_membership.group_name": group_name,
                })) === false
            ) {
                console.log("new function");
                const newGroupMembership = await GroupMembership.insertMany({
                    group_membership: [
                        { group_name: group_name, group_members: [member_name] },
                    ],
                });
                await newGroupMembership.save();
            } else {
                const UpdateGroupMembership = await GroupMembership.updateOne(
                    { "group_membership.group_name": group_name },
                    { $push: { "group_membership.$.group_members": member_name } },
                );
                console.log("update function");
                await UpdateGroupMembership.save();
            }
            ctx.response.status = 201;
            ctx.response.message = "A member added to group successfully";
        } catch (error) {
            ctx.body = {
                message: "Some validations failed for Group Member Creation",
                error: error.message,
            };
            console.log(error);
            ctx.throw(400, error);
        }
    });
    
    0 讨论(0)
  • 2020-12-05 00:36

    If you're searching by an unique index, then using UserModel.count may actually be better for you than UserModel.findOne due to it returning the whole document (ie doing a read) instead of returning just an int.

    0 讨论(0)
  • 2020-12-05 00:44

    For anybody falling on this old solution. There is a better way from the mongoose docs.

    var s = new Schema({ name: { type: String, unique: true }});
    s.path('name').index({ unique: true });
    
    0 讨论(0)
  • 2020-12-05 00:49

    Typically you could use mongoose validation but since you need an async result (db query for existing names) and validators don't support promises (from what I can tell), you will need to create your own function and pass a callback. Here is an example:

    var mongoose = require('mongoose'),
        Schema = mongoose.Schema,
        ObjectId = Schema.ObjectId;
    
    mongoose.connect('mongodb://localhost/testDB');
    
    var UserSchema = new Schema({
        name: {type:String}
    });
    
    var UserModel = mongoose.model('UserModel',UserSchema);
    
    function updateUser(user,cb){
        UserModel.find({name : user.name}, function (err, docs) {
            if (docs.length){
                cb('Name exists already',null);
            }else{
                user.save(function(err){
                    cb(err,user);
                });
            }
        });
    }
    
    UserModel.findById(req.param('sid'),function(err,existingUser){
       if (!err && existingUser){
           existingUser.name = 'Kevin';
           updateUser(existingUser,function(err2,user){
               if (err2 || !user){
                   console.log('error updated user: ',err2);
               }else{
                   console.log('user updated: ',user);
               }
    
           });
       } 
    });
    

    UPDATE: A better way

    The pre hook seems to be a more natural place to stop the save:

    UserSchema.pre('save', function (next) {
        var self = this;
        UserModel.find({name : self.name}, function (err, docs) {
            if (!docs.length){
                next();
            }else{                
                console.log('user exists: ',self.name);
                next(new Error("User exists!"));
            }
        });
    }) ;
    

    UPDATE 2: Async custom validators

    It looks like mongoose supports async custom validators now so that would probably be the natural solution:

        var userSchema = new Schema({
          name: {
            type: String,
            validate: {
              validator: function(v, cb) {
                User.find({name: v}, function(err,docs){
                   cb(docs.length == 0);
                });
              },
              message: 'User already exists!'
            }
          }
        });
    
    0 讨论(0)
提交回复
热议问题