These are chat archives for Automattic/mongoose

25th
May 2018
Søren Müller
@SorenMuller
May 25 2018 06:00

Hi,
I am kinda new to mongoose and mongo db, so hope someoen can help me here..
I have performance problems, when I call update..
My code

exports.CreateElement = function(versionId, documentName, newElement)
{
    return UpdateVersionWithConcurrencyProtection(versionId,
        function(version)
        {
            var doc = version.documents.find(e => e.name === documentName);

            // asign new id, if null
            if(newElement._id == null)
            {
                newElement._id = mongoose.Types.ObjectId();
            }
            updateset = cleanupElementHieraki(newElement);
            doc.elements.push(newElement);

            logger.info("CreateElement called - done.");
            return version;
    }, 0)
    .then(version => {
        var doc = version.documents.find(e => e.name === documentName);
         var element = doc.elements.find(e => e._id.equals(newElement._id));

        if(!element)
            {
            logger.info("CE : Element not found!!");
            doc.elements.forEach(e => {
                logger.info(e._id.toHexString() + ' ; ');
            })
            }
        return element;
    });
}

and

exports.UpdateVersionWithConcurrencyProtection = function(versionId, transformFunction, retries)
{
    logger.profile("==> Find by id");
    return Version.findById(versionId)
    .then(v =>
    {
        logger.profile("==> Find by id");

        let cur_nonce = v.nonce;
        logger.profile("==> transformFunction");
        let updatedVersion = transformFunction(v);
        logger.profile("==> transformFunction");
        updatedVersion.modifiedDate = new Date();
        updatedVersion.nonce = new mongoose.Types.ObjectId;

        logger.profile("==> update");
        return Version.updateOne({"_id":versionId, "nonce":cur_nonce}, updatedVersion, {new: true})    <=== HERE
        .then(res => {
            logger.profile("==> update");

            if(!res.nModified && retries < 10)
            {
                logger.log("Retrying...");
                //we weren't able to update the doc because someone else modified it first, retry
                //console.log("Unable to UpdateVersionWithConcurrencyProtection, retrying ", retries);

                //retry with a little delay
                setTimeout(function(){
                    return exports.UpdateVersionWithConcurrencyProtection(versionId, transformFunction, (retries + 1));
                }, 500 + (Math.random()*500));
            } else if(retries >= 10){
                //there is probably something wrong, just return an error
                //console.log("Couldn't update document after 10 retries in  UpdateVersionWithConcurrencyProtection");
                throw "Couldn't update document after 10 retries in  UpdateVersionWithConcurrencyProtection";
            }
            return updatedVersion;// Version.findOne({"_id":versionId});
        })
        .catch(err => {
            throw new errors.ErrorCalling("Error updating in: " + arguments.callee.toString())
        });
    })
    .catch(err =>
    {
        throw new errors.ErrorCalling("Error updating in: " + arguments.callee.toString())
    });
};

The place is marked by <=== HERE..
The updateOne takes at least 1 second and gets slower and slower..
I have app. 200 elements in list, so i db terms, that should be much..

I you need anymore info please let me know..

thanks alot

mushfau
@mushfau_twitter
May 25 2018 07:20
hi, does populate() work with dynamic reference if the referenced model is in another database?
Kev
@lineus
May 25 2018 09:21
@mushfau_twitter in order for cross database population to work you have to supply the collection that you're populating from to the model property of the populate options. If you had 2 or more dynamically referenced paths that you were populating from, you'd have to call populate once for each path. I'll try and sort out an example to clarify.
Kev
@lineus
May 25 2018 09:31
actually, maybe you could use the match populate option to do more than one :smile: I'll try that
mushfau
@mushfau_twitter
May 25 2018 09:40
var mongoose = require('mongoose');
var db8000 = mongoose.createConnection(process.env.REMOTE_DB_URI);

var Book = db8000.model('Book', new mongoose.Schema({
    title: String,
}, {timestamps: true}));

var Movie = db8000.model('Movie', new mongoose.Schema({
    title : String
}, {timestamps: true}));

var User = mongoose.model('User', new mongoose.Schema({
    name: String,
    hobby_type: String,
    hobby: {type: Schema.Types.ObjectId, refPath: 'hobby_type'}
}, {timestamps: true, toJSON: {virtuals: true}}));

        User.find({})
            .populate('hobby')
            .exec(function (err, users) {})

above is what i'm trying, basically the hobby in User model refers to either a Book or Movie document

@lineus, i tried like this as well

populate({path: 'hobby', model: 'hobby_type'})

but i'm getting the following error

{
            "message": "Schema hasn't been registered for model \"Book\".\nUse mongoose.model(name, schema)",
            "name": "MissingSchemaError"
        }

and btw, this work perfectly if the referenced models in the same database as the User

Kev
@lineus
May 25 2018 09:45
yeah, I've tried a few different permutations, but the only one I got to work so far was this one which required two populate calls, basically using where to split them up by collection.
cross-database population and dynamic refs don't work now, but it totally sounds like a reasonable feature request. If you open an issue for this, I'll try and come up with a way to make it work.
Keegan
@Keggatron
May 25 2018 15:02
Hi guys, I'm having an issue with using db.update(). Can someone tell me why this wouldn't add to the db? Appointment.update({date: date}, data, {upsert: true})
my data object would look something like this:
{ '10:00': 
[0]    [ { booked: true,
[0]        booker: 'Joe',
[0]        phone: '5555555' } ],
[0]   '10:30': 
[0]    [ { booked: true,
[0]        booker: 'John',
[0]        phone: '5555555'} ] }
Kev
@lineus
May 25 2018 16:51
@Keggatron you can use mongoose.set('debug', true) to see the actual update call to mongodb. is the error in the callback null, or is nModified in the result 0?
Keegan
@Keggatron
May 25 2018 17:38
data is an object with arrays in it
that object I put in the chat a few posts up is an actual console.log of my data object copied from the terminal