0

First, I'd like to start by saying I know there are several other posts out there somewhat related to inserting/updating if not exists. However, my case is a bit different and doesn't fit other posts.

I'm trying to insert a new document if username or email doesn't exists.

My code work fine, the only problem is my schema is not organized as I want. I want that the username to appear before email.

Problem

enter image description here

I already try to solve this problem and I did not succeed, but the problem exactly is in $or query operator, I don't know why it changes my schema!!

Here is my code

   //My Schema
   let newUserObject = {
    username: body.username,
    email: body.email,
    password: body.password
  };

 //upsert: true => create doc if username or email doesn't exists
 db.collection('users').updateOne( 
   {$or:[{username:newUserObject.username},{email:newUserObject.email}]},
  { $setOnInsert: newUserObject },
  { upsert: true }, function(err, res) {

    let response = { sucess: true, msg: "The User Created Successfully"};

    if(err){
        response.sucess=false;
        response.status=500;
        response.msg="There was a problem registering the user.";
    }else if(!res.result.upserted)
      response.msg="The User/Email is Already Exists";

    callback(response);
    client.close();
  });

Any information is much appreciated, Thanks

iLyas
  • 1,047
  • 2
  • 13
  • 30
  • What happens when you use only $set instead of $setOnInsert? – Navoneel Talukdar Feb 16 '18 at 16:56
  • It display the same thing, the problem is in query `$or` I don't know why it changes the schema! – iLyas Feb 16 '18 at 17:00
  • Possibly related: https://stackoverflow.com/a/41932272/691711 – zero298 Feb 16 '18 at 17:35
  • Why do you want `username` to apper before `email`? MongoDB document is a JSON object. You can directly access `username` in JSON object as `user.username`. It works more or less like hash table. I really didn't get your intentions, what problem does ordering solves in JSON object. – Ujjwal Feb 16 '18 at 18:20
  • I know, like you said, there is no problem. It's just for organizing the structure of my document, I'll leave it like this until I find a better answer or another way to do inserting if not exists. – iLyas Feb 16 '18 at 18:38

2 Answers2

0

To keep my documents organized, First I find the document that match my criteria with findOne() method after I call inside it an insertOne method :

db.collection('users').findOne({$or:[{username:newUserObject.username},{email:newUserObject.email}]},
      function(err, doc){
        assert.equal(err, null);

        let response = { sucess: true, msg: "The User Created Successfully"};

        //The User doesn't exist => Add New User
       if(!doc){
          db.collection('users').insertOne(newUserObject, function(err, res){
            if(err){
                response.sucess=false;
                response.status=500;
                response.msg="There was a problem registering the user.";
            } 
            callback(response);
            client.close();
          });
       }
       else{
               response.msg="The User/Email is Already Exists";
                callback(response);
                client.close();
       }
     });

Result

enter image description here

I'm not sure that my code is clean and follows a good practice, but it's a good solution for now.

iLyas
  • 1,047
  • 2
  • 13
  • 30
0

On Else if condition please update only !res.upserted

Ismail
  • 1,188
  • 13
  • 31