Search code examples
javascriptnode.jsmongoosemongoose-schemanode-request

Mongoose QueryStream and Request Module


When performing a QueryStream on a Model such as

User.find({}).stream().on('data', (user) => {
    request.post(someOptions, (error, response, body) => {
         if(!error && response.statusCode === 200) {
             user.someProperty = body.newValue;
             user.save((err) => {
                 if (err) console.log(err)
             });
         } else {
             console.log(error);
             console.log(response);
         }
}).on('end', () => {
    console.log('all users have new values');
});

I'm receiving the console output for the end event and then receiving an error:

all users have new values
TypeError: user.save is not a function
    at Request._callback

I'm assuming this means that the request.post function is running one too many times, as I tried to do this without a stream and simply a

.find({} (err, users) => {
     for(user in users) {
         request.post...
     } 
});

but this was returning a bad status code from the api I'm posting to as request.post() was sending an undefined value in the options I'm passing that I get from the user document, even though all the documents do have defined values. Although, I wasn't receiving a error for save not being a function.

Can anyone shed some light on what's happening?


Solution

  • Here's a simplified version assuming you don't need stream (which should be swapped out for cursor) and you have request-promise-native available

    const users = await User.find().exec()
    for(let user of users) {
        const body = await request.post(someOptions)
        if(body) {
            user.someProperty = body.newValue
            await user.save()
        }
    }
    

    From the code it looks like you're making the same post and updating the same value of every user. If that is the case, why not:

    const body = await request.post(someOptions)
    if(body) {
        await User.update(
          { },
          { $set: { someProperty: body.newValue } },
          { multi: true }
        )
    }