These are chat archives for Automattic/mongoose

21st
Jul 2018
phao5814
@phao5814
Jul 21 2018 08:56
hey guys, encountering a strange problem with insertMany(). would appreciate if someone could give me a hand here https://stackoverflow.com/questions/51454009/mongoose-insertmany-exec-returning-a-typeerror
Saket Patel
@Samy-33
Jul 21 2018 09:05
@phao5814 , according to the docs, Model.insertMany(...) returns a Promise, why do you need exec then?
phao5814
@phao5814
Jul 21 2018 09:06
@Samy-33 yeah i noticed that…is it just me or is it strange that some queries return a Promise and others don’t?
Saket Patel
@Samy-33
Jul 21 2018 09:07
I think, Model.insertMany among some more are not considered as queries.
    Model.deleteMany()
    Model.deleteOne()
    Model.find()
    Model.findById()
    Model.findByIdAndDelete()
    Model.findByIdAndRemove()
    Model.findByIdAndUpdate()
    Model.findOne()
    Model.findOneAndDelete()
    Model.findOneAndRemove()
    Model.findOneAndUpdate()
    Model.replaceOne()
    Model.updateMany()
    Model.updateOne()
These are the only queries available which are thenable but don't return a Promise
phao5814
@phao5814
Jul 21 2018 09:10
ahhh gotcha :) you wouldn’t happen to know why the inconsistency exists would you? all good if you don’t (I’ll just ask it on SO or somewhere appropriate)
Kev
@lineus
Jul 21 2018 09:57
@phao5814 @Samy-33 Model.insertMany doesn't return a Query object because none of the helper methods like .sort() or .lean() are relevant to the operation, so it's a promise instead.
Saket Patel
@Samy-33
Jul 21 2018 10:15
Thanks @lineus for clarifying
phao5814
@phao5814
Jul 21 2018 10:19
@lineus ahhh i see i see makes sense :) thanks for explaining
Kev
@lineus
Jul 21 2018 10:21
anytime :smile:
Kev
@lineus
Jul 21 2018 10:49
@Samy-33 did you figure out the answer to your question about using a single connection for your app?
Kev
@lineus
Jul 21 2018 12:16

@thehme There are a couple of small issues in your gist.

The first is that your update string should start with dataTypes not program.dataTypes ( your schema doesn't have a program path to update ).

The second is that you are passing a query condition into Document.update() as the first parameter, which is where the update doc should go ( it's being called on the doc so a condition isn't necessary ). This results in mongoose interpreting your update doc as the options parameter which results in no changes to those paths.

slightly modified gist with working updates

Saket Patel
@Samy-33
Jul 21 2018 13:34
@lineus,
This => {This connection object is then used to create and retrieve models. Models are always scoped to a single connection.}
Does this mean, that a single connection instance is used whenever I refer to same connection from a module?
For example I initialize my connection in db.js and wherever I import that connection from db.js, it will be same one instance?
Kev
@lineus
Jul 21 2018 13:41
what does db.js look like @Samy-33 ?
Saket Patel
@Samy-33
Jul 21 2018 13:42
db.js
import mongoose from 'mongoose';

const uri = 'mongodb://localhost:27017/test';
const options = {
...
}

const connection = mongoose.createConnection(uri, options);

export default connection;
Kev
@lineus
Jul 21 2018 14:10
@Samy-33 you should get the same connection in each import. I tested with this gist . There are only 2 connections, the default connection mongoose.connections[0] and the one created by your db.js file.
Saket Patel
@Samy-33
Jul 21 2018 14:13
Thank you so much @lineus :)
Kev
@lineus
Jul 21 2018 14:14
anytime!
Berian
@chaiwa-berian
Jul 21 2018 20:16
How do I handle error when MongoDB is down? Tested this endpoint, but it doesn't get hit at all if the request is sent when the database server is down. I am using mongoose
//GET api/silcgroups
exports.getAllSILCGroups = function(req, res){
    SILCGroup.find(req.query, function(err, silcgroups){
        if(err) {
            console.log(err);
            return res.json(err);
        }
        else  return res.json(silcgroups);
    });
};
Berian
@chaiwa-berian
Jul 21 2018 22:17
Is there a way I can only update the fields that have changed? I do have a bunch of fields exposed to the client via the API, and the client can update whatever field needs to be updated! But when I receive them at the backend, I would like to find a quick way to create an update query so it only contains modified fields! Any ideas?
Kev
@lineus
Jul 21 2018 22:39
@chaiwa-berian did you answer your first question already?
Berian
@chaiwa-berian
Jul 21 2018 22:40
@lineus nope! Help!!!
Kev
@lineus
Jul 21 2018 22:45

There are a couple of different scenarios that come up most often.

Mongodb Server isn't running when you start your http server

for this, you can write your http start up code so that it only runs once you've successfully connected to the db. You can do this with either the 'connected' event listener on the mongoose connection, or in the callback to mongoose.connect() or using promises etc.

You lose the connection to the Mongodb Server

for this, you can write an event listener to attach to the 'disconnected' event on the connection.

mongoose buffers model commands until you connect by default. So if you start your http server without waiting for the db connection, it's possible to find yourself in a situation where your http server is up and isn't connected to the db.

Mongoose will silently buffer any queries, inserts etc until you connect. This behavior can be disabled by passing bufferCommands: false in your connection options.

Berian
@chaiwa-berian
Jul 21 2018 22:49
Lovely!
So when bufferCommands is false will my function be able to throw error on DB server down?
Idealy, I would like to be able to send some info back to the client when DB server is down
Kev
@lineus
Jul 21 2018 22:56
you'll get a TypeError for which ever method you called on the model. For instance Model.find() on a Model that isn't connected with bufferCommands set to false will return TypeError: Cannot read property 'find' of null along with the stacktrace etc.
Berian
@chaiwa-berian
Jul 21 2018 22:57
I.e. if a client hits any of the endpoints, and DB connection is down, I want to gracefully notify them!
Ok sounds good, thanks for your help @lineus
Kev
@lineus
Jul 21 2018 22:58
anytime :smile:
Berian
@chaiwa-berian
Jul 21 2018 22:59
👍
And on my second question? @lineus
Kev
@lineus
Jul 21 2018 23:01
giving that one some thought now
Berian
@chaiwa-berian
Jul 21 2018 23:03
Great!
Kev
@lineus
Jul 21 2018 23:04
when you build the form in the client to change the data, are you populating the fields with an object retrieved from the db?
Berian
@chaiwa-berian
Jul 21 2018 23:10
Right now am justing building the API with tests via POSTMAN, no forms etc
So the body of the request contains whatever fields were modified by the client.
belubit
@belubit
Jul 21 2018 23:14
Wonderful people, can anyone help me with a populate issue?
I want to populate but only with items created after the parent document was created
Kev
@lineus
Jul 21 2018 23:20
@chaiwa-berian if you come up with an interesting solution, let me know. I'll sleep on it and share any ideas I come up with.
Berian
@chaiwa-berian
Jul 21 2018 23:21
Cheers👍Linkup later!
Kev
@lineus
Jul 21 2018 23:21
@belubit if the foreign docs have a timestamp, you should be able to use a match in the population object with $gt on the created date.
belubit
@belubit
Jul 21 2018 23:22
I haven't implemented timestaps yet, but everything has a created date, in full utc date format
as in the auto timestamp, only just read about it today
Kev
@lineus
Jul 21 2018 23:23
that should work just fine, I meant timestamp in the generic sense.
belubit
@belubit
Jul 21 2018 23:23
how do I reference the parent document date?
will paste code
let groupQuery = grouping.find({ owner : req.user._id}).populate(
{
path : 'items',
match: { created: { } }
I wanted created to be the parent creation date, if that makes sence
*sense
Kev
@lineus
Jul 21 2018 23:36
here's a standalone example that shows what I think you're trying to do
belubit
@belubit
Jul 21 2018 23:38
Wow, thanks for that! But I don't think that it, or more probably I, will work
Berian
@chaiwa-berian
Jul 21 2018 23:39
@belubit syntax looks good, just make sure the match is like : `match: {created: {req.user.created_date}}
belubit
@belubit
Jul 21 2018 23:41
I think that match: {created: } thing is the issue, as that date I want it to be greater than is from the query, unless I do another query beforehand to get the date
I want to find all groups (each group has a created date), then populate each group with all the items (separate scheme and collection), which are both in the group and created after the group was created
as some of the items are created before the group was created
Kev
@lineus
Jul 21 2018 23:43
that's what match: { createdAt: { $gte: test.createdAt }} in my example does. Where the date comes from is immaterial as long as it's a valid date.
it compares the value of the createdAt field in the foreign doc and only returns it if it matches.
belubit
@belubit
Jul 21 2018 23:44
exactly, but each group has a different date, and I wondered if I could grab that date in the query before the population is executed
belubit
@belubit
Jul 21 2018 23:50
So for each result it finds, I would like the populate to use that resultants creation date
Berian
@chaiwa-berian
Jul 21 2018 23:51
@belubit can you try @lineus 's solution and compare the results? It looka correct to me!
belubit
@belubit
Jul 21 2018 23:52
I'll give give it a go
(some of it goes over my head)
Kev
@lineus
Jul 21 2018 23:53
oh, I see. the group is the local doc and item is the foreign doc and you want to change the value of the date criteria you match in the item doc based on each group doc's date.
you can call populate on the doc itself. I'll adjust my example and see if what i'm thinking lines up with what you're wanting.
Berian
@chaiwa-berian
Jul 21 2018 23:55
Or are you asking like: get me items that were created after query_date and their groups must have been created before their items? Did I hear you?
belubit
@belubit
Jul 21 2018 23:59
I will try to explain it as best I can, as I think I have failed so far