These are chat archives for Automattic/mongoose

4th
Sep 2018
Joe Early
@JoeEarly
Sep 04 2018 09:37

Hi all, am strugoing with 2 things here. I have aded an complete modal and I need to perform 2 things.

1: get the list of values from the array "linkedOffers"
2: Pass this to a .find() and return a document containing all the linkedOffers

Couold ome advise off an apporach and Ill give it a go :)

{
    "_id" : ObjectId("5b8dbbec6ac6d662f4835cbb"),
    "uuid" : "7ad29390-afcc-11e8-a91d-d3b9c514c165",
    "discipline" : "",
    "title" : "",
    "category" : "",
    "state" : "",
    "addedDate" : ISODate("2018-09-03T22:55:40.361Z"),
    "desc" : "",
    "requester" : {
        "_id" : ObjectId("5b3d112821b3ef2720677976"),
        "name" : "",
        "address1" : "",
        "address2" : "",
        "town" : "",
        "country" : "United Kingdom",
        "countryCode" : "GB",
        "postzip" : "",
        "shortPostcode" : "",
        "email" : "",
        "username" : "",
        "__v" : 0,
        "resetPasswordExpires" : ISODate("2018-07-06T00:08:27.348Z"),
        "resetPasswordToken" : ""
    },
    "__v" : 0,
    "linkedOffer" : [ 
        "offerId-f6f65700-af94-11e8-abce-f12a667f949f", 
        "offerId-f6f65700-af94-11e8-9999-f12a667f949f"
    ]
}
Berian
@chaiwa-berian
Sep 04 2018 09:39

Why do I get the MissingSchema error when I try to populate in the Schema.pre('find') hook?

SILCGroupSchema.pre('find', function(){
    this.populate('members')
});

The schema is defined as below:

let SILCGroupSchema = new Schema({
    name: { type: String, required: true,minlength: 5, maxlength: 50, alias: 'Group Name' }, 
    whatsapp_url: { type: String, required: true, alias: 'Group URL' },
    location: { type: String, required: true, alias: 'Group Location' },
    date_formed: { type: String, required: true, alias: 'Group Formation Date' },
    active: { type: Boolean, required: true, alias: 'Active' },
    members: [{ type: Schema.Types.ObjectId, ref: SILCGroupMember }]

}, {timestamps: true});
Kev
@lineus
Sep 04 2018 11:10

@chaiwa-berian the value of ref in the members path should be the same as the string you used as the first argument to mongoose.model() for the referenced Model. So if you had

  const SILCGroupMember = mongoose.model('xyz', groupSchema)

then your members path would be defined like:

  members: [{ type: Schema.Types.ObjectId, ref: 'xzy' }]
Kev
@lineus
Sep 04 2018 11:23
@JoeEarly can you elaborate on what you're trying to accomplish? are you trying to get the linkedOffers from one document, and find all other documents with the exact same set of offers? or do you want to get the linkedOffers from one document and then find all other documents with any of the same offers?
Joe Early
@JoeEarly
Sep 04 2018 11:27

the array linkedOffers has a list of offerIDs. I'd like to get the linkedOffers list based on requester.username and then use this list of IDs in a find()

So, give me a list of offers based on the user who opened them.

Joe Early
@JoeEarly
Sep 04 2018 11:34

I attempted the following by looping over a find all requests, but its giving me an array of arrays, whereas I'd like just one array list, so rather than push, more like append the value.

 Request.getLinkedOffers(req.user.username, function(err, docs){

    for(let i = 0; i < docs.length; i++) {

      offerIdList.push(docs[i]._doc.linkedOffer)

      console.log(offerIdList)
    }
  })

Which calls a cimple find all requests by username

// Find by linkedOffers.
module.exports.getLinkedOffers = function(username, callback) {
  const query = { "requester.username": username }
  Request.find(query, callback)
}
Has mongoose something easier ?
Berian
@chaiwa-berian
Sep 04 2018 11:51

@chaiwa-berian the value of ref in the members path should be the same as the string you used as the first argument to mongoose.model() for the referenced Model. So if you had

  const SILCGroupMember = mongoose.model('xyz', groupSchema)

then your members path would be defined like:

  members: [{ type: Schema.Types.ObjectId, ref: 'xzy' }]

Thanks @lineus , very helpful! I am still having trouble adding refs to the members property of the SILCGroup. So I have an endpoint for adding members to the group given the group id but in the controller for the SILCGroupMember, in the callback for the silc_group_member.save() method, I would like to save the new member to the SILCGroupMember collection and then push the _id for the new member to the members property of the SILCGroup. I also want them wrapped in a transaction so if either the operation to save a member or update the group fails, the whole transaction is rolled back! Any ideas?

Kev
@lineus
Sep 04 2018 11:58
@JoeEarly I thought I would be able to concat each array in a forEach loop but I ended up having to nest 2 forEach loops. this example seems to get the job done though
I'll look into the concat thing, it might just be my naivety
@chaiwa-berian are you using mongodb > 4.0 ?
Joe Early
@JoeEarly
Sep 04 2018 12:03
@lineus I thank you, may take me amomen to understand that, loads of naivety here too
Kev
@lineus
Sep 04 2018 12:05
no worries, I'm not going anywhere for a while. I find it's easier to reason and talk about this stuff with a complete example like this. I hope it helps more than it hurts :smile:
Berian
@chaiwa-berian
Sep 04 2018 12:05
@lineus I am using v3.6.5 but I can upgrade!
Kev
@lineus
Sep 04 2018 12:06
@chaiwa-berian yeah, you'll need to be running mongodb 4 or higher to get transactions. Also make sure you're using the latest version of mongoose.
Berian
@chaiwa-berian
Sep 04 2018 12:07
@lineus Ok, do you have a good example?
Kev
@lineus
Sep 04 2018 12:07
@chaiwa-berian I'll write one now :smiling_imp:
Berian
@chaiwa-berian
Sep 04 2018 12:08
@lineus lol. :+1:
Kev
@lineus
Sep 04 2018 12:39
@chaiwa-berian here is an example
Berian
@chaiwa-berian
Sep 04 2018 12:41
@lineus Thank you @lineus , greatly appreciated!
Kev
@lineus
Sep 04 2018 12:45
I hope it helps :)
Kev
@lineus
Sep 04 2018 12:55
@JoeEarly I'm a dork. Array.prototype.concat() doesn't mutate the existing array, it returns a new array. So that static method is better written as:
schema.statics.myFunc = function(name) {
  return Test.find({ 'requester.username': name })
    .then((docs) => {
      let ret = [];
      docs.forEach(d => {
        ret = ret.concat(d.arr);
      });
      return ret;
    });
};
Joe Early
@JoeEarly
Sep 04 2018 12:57
yea spotted that on the one I did and I have an array here now as expected, my issue is now it doesnt finish in time so I have to promisie.async her up here and hopefully that will be me done with this one