KiSa87
KiSa87

Reputation: 23

Saving mongoose schema without creating a new schema

I'm using the following code, which is also working

'use strict';

const Profile = require('../database/shemas/profileSchema');
const ProfileHelper = require('../helpers/profileHelper');
const logger = require('../utils/logger');

const createUpdateProfile = (req, res) => {
    //Fillout Schema
    let uuid = req.user.identities[0].id;
    let provider = req.user.identities[0].provider;
    let email = req.user.email;
    let firstName = req.user.name.split(' ').slice(0, -1).join(' ');
    let lastName = req.user.name.split(' ').slice(-1).join(' ');
    let pictureUrl = req.user.picture;
    let profileToSafe = new Profile({
        uuid,
        provider,
        email,
        firstName,
        lastName,
        pictureUrl
    });
    //createUpdate
    if (!!!uuid) {
        res.status(400).send('Invalid argument supplied');
    } else {
        Profile.findOne({ uuid }).then(object => {
            if (object !== null) {
                var upsertData = profileToSafe.toObject();
                delete upsertData._id;
                delete upsertData.uuid;
                delete upsertData.provider;
                Profile.update({ uuid }, upsertData, { upsert: true }, function (err, raw) {
                    if (err) {
                        console.log('callback -> err', err);
                    }
                    console.log('callback -> raw', raw);
                    res.status(200).send('Successful operation');
                });
            } else {
                profileToSafe.save();
                res.status(200).send('Successful operation');
            }
        })
    }
}

This is my schema

'use strict';

// Mongoose schema definitions
const mongoose = require('mongoose');
const Schema = mongoose.Schema;

// Create Profile Schema
const profileSchema = new Schema({
    uuid: {
        type: String,
        required: true,
        unique: true
    },
    provider: {
        type: String,
        required: true
    },
    email: {
        type: String,
        required: true,
        unique: true,
        trim: true
    },
    firstName: {
        type: String,
        required: true
    },
    lastName: {
        type: String,
        required: true
    },
    birthday: {
        type: String,
        default: ""
    },
    pictureUrl: {
        type: String,
        default: ""
    }, // Later we can add a default image for users who use cloud directory login
    onboardingDone: {
        type: Boolean,
        required: true,
        default: false
    }
}, {
        timestamps: true, // Add CreatedAt and updatedAt fields automatically
        strict: 'throw'
    });

const Profile = mongoose.model('Profile', profileSchema);

module.exports = Profile

But the trick was, that I needed to delete the id

    delete upsertData._id;

A colleague persists that this is due wrong usage of

    let profileToSafe = new Profile({ ...

I tried different variations but none of them worked. Is there really another (more) correct way of doing what I want?

Edit: I did what @Sridhar suggested but now I'm running into a problem with the timestamp. Even when I delete it from the schema.

Upvotes: 0

Views: 186

Answers (1)

Sridhar
Sridhar

Reputation: 11786

You can use mongoose's findOneAndUpdate() with upsert:true option.

Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback.

Options

upsert: bool - creates the object if it doesn't exist. defaults to false.

Making those changes to your code

'use strict';

const Profile = require('../database/shemas/profileSchema');
const ProfileHelper = require('../helpers/profileHelper');
const logger = require('../utils/logger');

const createUpdateProfile = (req, res) => {

  const uuid = req.user.identities[0].id;
  const provider = req.user.identities[0].provider;

  const email = req.user.email;

  const firstName = req.user.name.split(' ').slice(0, -1).join(' ');
  const lastName = req.user.name.split(' ').slice(-1).join(' ');
  const pictureUrl = req.user.picture;

  if (!uuid) {
    return res.status(400).send('Invalid argument supplied');
  }

  Profile.findOneAndUpdate({
    uuid
  }, {
    provider,
    email,
    firstName,
    lastName,
    pictureUrl,
    $setOnInsert: {
      createdAt: Date.now()
    },
    updatedAt: Date.now()
  }, {
    upsert: true
  }).then(() => {
    res.status(200).send('Successful operation');
  }).catch((err) => {
    console.log('callback -> err', err);
    // You can send appropriate response here
  });

}

Upvotes: 1

Related Questions