These are chat archives for Automattic/mongoose

18th
Oct 2018
calder-western
@calder-western
Oct 18 2018 00:57
Hi there - I need help. I have a findOneAndUpdate call with upsert:true, new:true that is writing the data twice to the database.
From the ID, I can see it has happened a fraction of a second apart - 5bc7d53bc383af5dcc81f8ca, 5bc7d53bc383af5dcc81f8cb,
calder-western
@calder-western
Oct 18 2018 01:03
Using v5.2.2
calder-western
@calder-western
Oct 18 2018 01:45
Correct me if I am wrong, I am using Bluebird Join and expecting findOneAndUpdate to return a promise - it doesn't - so I appended exec() to end. All seems ok now. Still not sure on why it would write two duplicate records to database
Zoey Cluff
@ZoeyCluff
Oct 18 2018 05:17
Hey y'all.
Can someone help me figure out how to take my model and schema and return a find?
I'm either getting [] or I'll get Query {
_mongooseOptions: {},
_transforms: [],
mongooseCollection:
NativeCollection {
collection: Collection { s: [Object] },
opts:
{ bufferCommands: true,
capped: false,
'$wasForceClosed': undefined },
name: 'boxmacs',
collectionName: 'boxmacs',
conn:
NativeConnection {
base: [Mongoose],
collections: [Object],
Kev
@lineus
Oct 18 2018 09:55
@calder-western Queries don't return promises, they return Query objects which are thenables i.e. they have .then and .catch methods. Calling .exec without a callback will return a promise. Example gist here. It sounds like you might be passing in a callback function and utilizing the promise simultaneously which will result in duplicate operations.
@ZoeyCluff are you passing in a callback to find() or using await|then|exec? Check out the Query docs here. Feel free to post a code sample here of how you are calling find() as well.
Grant Allor
@gallor
Oct 18 2018 16:16
Howdy fellow gitters. New to Mongoose and just got handed a pre-configured project that I need to ensure has proper failover.
I currently have a Mongo replica set with a node in 4 regions in AWS with then a separate ELB in each of those regions making calls to the db. What I'm wanting is each ELB in their region to only query their region specific node (for reads of course, I'll figure out writes later) but also ensure that if that node goes down there's a fallback. It's unclear from the docs what Mongoose is doing when making a replSet connection. ie mongoose.connect('mongodb://user:pw@host1.com:27017,host2.com:27017,host3.com:27017/testdb');
Does it primarily read from the one you list first then use the others as fallbacks if the first connection fails or does it connect to the pool and queries from the primary? Any help would be greatly appreciated! Thanks
Berian
@chaiwa-berian
Oct 18 2018 16:22
Hi. How can I build a custom async validation that checks an array of ids if they actually exist in the database? Here is my attempt but I am not getting anything meaningful:
    silc_groups: [{ 
        type: Schema.Types.ObjectId, 
        ref: 'SILCGroup', required: true,
        validate: {
            isAsync: true,
            validator: function(v, callback){

                SILCGroup.findById(v, function(err, silc_group){
                        if(err){
                            callback(err);
                        }
                        return !silc_group;
                    });
            },
            message: "silc_groups field values must be valid existing group ids"
        }
    }]
Berian
@chaiwa-berian
Oct 18 2018 16:53

Hi. How can I build a custom async validation that checks an array of ids if they actually exist in the database? Here is my attempt but I am not getting anything meaningful:
```
silc_groups: [{
type: Schema.Types.ObjectId,
ref: 'SILCGroup', required: true,
validate: {
isAsync: true,
validator: function(v, callback){

            SILCGroup.findById(v, function(err, silc_group){
                    if(err){
                        callback(err);
                    }
                    return !silc_group;
                });
        },
        message: "silc_groups field values must be valid existing group ids"
    }
}]

I refactored to the below and seems to work but I am not sure if this is the best practice: silc_groups: [{
type: Schema.Types.ObjectId,
ref: 'SILCGroup', required: true,
validate: {
isAsync: true,
validator: function(v, callback){

            return SILCGroup.findById(v, function(err, silc_group){
                    if(err){
                        return callback(err);
                    }
                    if(silc_group){
                        return true;
                    }
                    else {
                        return false;
                    }
                });
        },
        message: "silc_groups field values must be valid existing group ids"
    }
}]```
Kev
@lineus
Oct 18 2018 16:53
@chaiwa-berian if you are saying that you only want the array to contain _ids that are from documents that exist in the collection, you probably want to return !!silc_group, the single ! will negate the result, returning false for a document that exists ( which causes validation to fail ). !! will return false for null or true for a found doc.
Berian
@chaiwa-berian
Oct 18 2018 16:55
@lineus Thanks, you are right! Edited, but I am curious if that is the common practice? Like checking via custom validators, what would you recommend?
Kev
@lineus
Oct 18 2018 17:01
@chaiwa-berian I can't think of a reason not to do it that way, or a better way to do it.
seems reasonable to me
Berian
@chaiwa-berian
Oct 18 2018 17:03
@lineus Thank you! Very helpful :)
Kev
@lineus
Oct 18 2018 17:25

@gallor

What I'm wanting is each ELB in their region to only query their region specific node (for reads of course, I'll figure out writes later)

I believe you can specify the readPreference option to 'Nearest' in the connection settings to get each process to read from the replica set member with the lowest network latency. As for writes, afaik they'll always go to the primary.

Grant Allor
@gallor
Oct 18 2018 17:52
@lineus That looks like that would do it for reads! Thanks. And yeah, as for writes I think you're right, so I'll have to figure out a different way to minimize my latency for global calls. Thanks again.