I have a user_batch collection. It contains following documents:
[{
_id: ObjectId("594baf96256597ec035df23c"),
name: "Batch 1",
batchSize: 30,
users:[]
},
{
_id: ObjectId("594baf96256597ec035df234"),
name: "Batch 2",
batchSize: 50,
users:[]
}]
In find query I want to project only name and batchSize. But when I execute find query from nodejs, I'm getting entire document in query result. Query:
db.collection('user_batch').find({}, {name: 1, batchSize: 1}).toArray((err, result) => {
if(err)
console.log(err)
else
console.log(result)
})
If I just pass {name: 1} then it will project _id and name. But if I pass batchSize then it will return entire document.
Note: I'm not facing this issue while executing this query in Mongo Shell
You are correct that the driver incorrectly interprets this as the batchSize
option and ignores the projection statement.
The correct way to do this though in modern driver releases is to actually use the .project()
"cursor method" instead. This is more consistent with other language driver implementations.
db.collection('collection').find()
.project({ name: 1, batchSize: 1})
.toArray();
As a full demonstration:
const mongodb = require('mongodb'),
MongoClient = mongodb.MongoClient;
(async function() {
let db;
try {
db = await MongoClient.connect('mongodb://localhost/test');
// New form uses .project() as a cursor method
let result = await db.collection('collection').find()
.project({ name: 1, batchSize: 1})
.toArray();
console.log(JSON.stringify(result,undefined,2));
// Legacy form confuses this as being a legacy "cursor option"
let other = await db.collection('collection')
.find({},{ name: 1, batchSize: 1 })
.toArray();
console.log(JSON.stringify(other,undefined,2));
} catch(e) {
console.error(e)
} finally {
db.close()
}
})()
Produces the output:
[
{
"_id": "594baf96256597ec035df23c",
"name": "Batch 1",
"batchSize": 30
},
{
"_id": "594baf96256597ec035df234",
"name": "Batch 2",
"batchSize": 50
}
]
[
{
"_id": "594baf96256597ec035df23c",
"name": "Batch 1",
"batchSize": 30,
"users": []
},
{
"_id": "594baf96256597ec035df234",
"name": "Batch 2",
"batchSize": 50,
"users": []
}
]
Where the first output form is the corrected one, using .project()
The syntax of Find
has changed. Below is what I needed to know to solve this problem. This is excerpted from https://github.com/mongodb/node-mongodb-native/blob/master/CHANGES_3.0.0.md#find
find
and findOne
no longer support the fields
parameter. You can achieve the same results as
the fields
parameter by using Cursor.prototype.project
or by passing the projection
property
in on the options object . Additionally, find
does not support individual options like skip
and
limit
as positional parameters. You must either pass in these parameters in the options
object,
or add them via Cursor
methods like Cursor.prototype.skip
.
2.x syntax:
const cursor = coll.find({ a: 42 }, { someField: 1 });
3.x syntax:
const cursor = coll.find({ a: 42 }).project({ someField: 1 });
/* OR */
const cursor = coll.find({ a: 42 }, { projection: { someField: 1 } });
©2020 All rights reserved.