These are chat archives for Automattic/mongoose

23rd
Apr 2018
Roy Shao
@ycshao
Apr 23 2018 01:56
I have a User model which username is a unique key which has a custom unique validator. I bumped into a problem that when I want to updatea a user and username is not changed, it gives validation error. Is it good practise to only $set things that has been changed when calling findOneAndUpdate? If so, I have to have a logic to diff user data before calling findOneAndUpdate, which I feel is a little bit too heavy.
this.model.findOneAndUpdate(
        { _id: req.params.id },
       {
        $set: {
          username: req.body.username,
          role: req.body.role
        }
      },
        { runValidators: true },
        (err) => {
          if (err) {
            console.error(err);
            return res.sendStatus(400);
          }
          return res.sendStatus(200);
        }
      )
const userSchema = new mongoose.Schema({
  username: {
    type: String,
    required: [true, 'username is required.'],
    trim: true,
    unique: true, // unique index, not unique validation
  },
…
});
Kev
@lineus
Apr 23 2018 08:12
@ycshao what does your validator look like? what is the exact error you get?
Roy Shao
@ycshao
Apr 23 2018 12:26

I basically count how many records match the input.

```

export function uniqueValidator(model: string, schema: mongoose.Schema, path: string, value: any) {
    return new Promise(function (resolve, reject) {
        mongoose.model(model, schema).count({ [path]: value }, function (err, count) {
            if (err === null) {
                // If `count` is greater than zero, "invalidate"
                resolve(!count);
            }
            else {
                resolve(false);
            }
        });
    });
}
So in this case, count is 1 because it’s the record I want to update itself.
Ghost
@ghost~5928d90bd73408ce4f629b9e
Apr 23 2018 14:40
can anyone suggest how to reduce the repetitive use of findOne within route controllers? should create a utility for findOne function and use promise approach for this matter?
panigrah
@panigrah
Apr 23 2018 14:45
What are you doing with the findOne?
Ghost
@ghost~5928d90bd73408ce4f629b9e
Apr 23 2018 15:12
@panigrah i have some findOne that finds with email and only sends the found data as response and im not using any other methods like .select('+password')
@panigrah is this okay? if im not mistaken findByEmail is already a promise? but still...
    findByEmail: (email) => {
        return new Promise((resolve, reject) => {
            Account.findOne({user_email: email},
                (err, user) => {
                    if(err){
                        reject(err)
                        throw err;
                    }

                    if(user){
                        resolve(user)
                    }
                })
        })
    }
 utility.findByEmail(req.body.email)
        .then(user => {
            console.log(user)
            res.send(user)
        })
        .catch(err => {
            console.log(err)
        })
panigrah
@panigrah
Apr 23 2018 15:23
Yes it’s already a promise so you don’t need again. What will you gain though with the additional layer? The amount of code you need seems almost the same each time you call the utility function
It does help however if you choose to change the account lookup later - that way you don’t have to change it everywhere
Ghost
@ghost~5928d90bd73408ce4f629b9e
Apr 23 2018 15:31
So okay to have same findOne on different routes? then i don't have to worry and just leave it like that. thanks
panigrah
@panigrah
Apr 23 2018 15:33
If you keep repeating the same code for a reason e.g. that’s how you check if user is logged in - then you can try a different way but I don’t see an issue to repeat the findOne
Ghost
@ghost~5928d90bd73408ce4f629b9e
Apr 23 2018 15:35
@panigrah Thanks for the response, another question is there a method that i can use for updating unknown fields? Like a user might update the email or the username or maybe both but i don't know which the user might update, is there a method for that?
panigrah
@panigrah
Apr 23 2018 15:41
It depends on how you are receiving the updated fields. I call update() with different arguments. Eg: `let value={}; if(params.email) value.email = params.email; and so on. Then call the update.
Ghost
@ghost~5928d90bd73408ce4f629b9e
Apr 23 2018 15:52

@panigrah i'm doing something like this in the client

 const originalKeyValue = originalValue.email || originalValue.name
 fetch(`/profile/users/${originalKeyValue}`
               .....

then in server i only have this for now since i don't know how to update it i can't think of how would i find out if both needs to be updated

    user_update: (req, res) => {
        console.log(req.body.entry)
        if(req.body.originalValue.email){
            res.json({message: 'you want to change the email'})
        } else if(req.body.originalValue.name) {
            res.json({message: 'you want to change the name'})
        }
@panigrah both originalValue.email and originalValue.name can be sent at the same time since i am using React JS it's wrapped in a instance of a component
Also I'm doing this on componentWillUnmount so guaranteed the data to be change is sent at the same time..
Kev
@lineus
Apr 23 2018 16:09
@ycshao how do you call uniqueValidator()