Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mongo NodeJS project() is not a function

I wanted to exclude some attributes from the result. I read the specification: https://docs.mongodb.com/manual/tutorial/project-fields-from-query-results/ - I need to use project function. So I chained this call but the code starts failing. The code worked fine without .project({ auth: 0, prefs: 0, consent: 0 }). Where is the issue? I found this answer which looks similar: https://stackoverflow.com/a/51732851/1639556.

package.json

"mongodb": "^3.4.1",

Lambda

exports.handler = (payload, context, callback) => {
    const userId = payload.pathParameters.userId;
    context.callbackWaitsForEmptyEventLoop = false;   
    mongo.connectToDatabase()
        .then(db => {
            return findUser(db, userId);
        })
        .then(user => {
            console.log("User fetched");
        })
};

function findUser(dbClient, userId) {
    return dbClient.db()
        .collection("users")
        .findOne({ "_id": userId })
        .project({ auth: 0, prefs: 0, consent: 0 })
        .then(doc => { return doc; });
}

Error

2020-01-28T11:52:34.555Z        0701f485-3770-1f43-f838-4baec8377293    INFO    Request failed TypeError: dbClient.db(...).collection(...).findOne(...).project is not a function
at findUser (/var/task/src/handlers/users/getUser.js:41:10)
at mongo.connectToDatabase.then.db (/var/task/src/handlers/users/getUser.js:19:20)

PS I am curious if the projection is done at client side or server side. It is confusing to me that the project function is AFTER the find call.

like image 470
Leos Literak Avatar asked Dec 02 '22 09:12

Leos Literak


2 Answers

.project() is a cursor function, so while you can use it on cursor methods, findOne does not return a cursor. What you can do is use the project as a query option.

In the documentation you linked theres an example of how to use it, in the follow case:

db.inventory.find( { status: "A" }, { item: 1, status: 1, instock: { $slice: -1 } } )

The projection option is { item: 1, status: 1, instock: { $slice: -1 } }.

So in your case you'll need to change your code to:

return dbClient.db()
    .collection("users")
    .findOne({ "_id": userId }, { auth: 0, prefs: 0, consent: 0 })
    .then(doc => { return doc; });

Or in case your using version 3+ of the Mongod nodejs driver change into:

return dbClient.db()
    .collection("users")
    .findOne({ "_id": userId }, {projection: { auth: 0, prefs: 0, consent: 0 }})
    .then(doc => { return doc; });
like image 128
Tom Slabbaert Avatar answered Dec 04 '22 06:12

Tom Slabbaert


project() is only a function of the find() operation. It doesn't work with findOne() (as of mongoDB Node.js driver 3.6.0) and has to be passed in the options for that call. That's why the accepted answer works, but you've seen the project() function elsewhere.

The mongo documentation here only shows the .project() function after a find() call: https://docs.mongodb.com/drivers/node/fundamentals/crud/read-operations/project

like image 25
emich Avatar answered Dec 04 '22 06:12

emich