Second parameter to limit fields in find() not working in Mongodb - mongodb

Mongodb Database view
I want to omit the _id field in my result
MongoClient.connect("mongodb://localhost:27017/",function(err,client){
var db = client.db("customerDetails");
db.collection("customerName").find({},{ _id : 0}).toArray(function(error,result){
console.log(result);
client.close();
});
});
Looked up from w3 schools
But somehow its not working. I still get the _id field in my result object.
What am i missing ??

In version 3.0 of the mongodb driver, the second parameter to find() is the options object, not the projection document. See the documentation here. To send a projection document, set the projection property of the options document. E.g.
db.collection("customerName").find({}, { projection: { _id: 0 } })
Alternatively, use the project method:
db.collection("customerName").find({}).project({ _id: 0 })
In version 2.2 of the mongodb driver, the second argument of find was indeed the projection document. This has changed in the latest version (3.0). So some blog posts might not be up to date. See the relevant section of the 3.0 changelog here.

In version 3.4.9 of the mongodb you can simply achieve this by:
db.getCollection('data').find({}, { _id: 0 })

This should work. Using the boolean "false".
MongoClient.connect("mongodb://localhost:27017/",function(err,client){ var db = client.db("customerDetails"); db.collection("customerName").find({},{ _id : false}).toArray(function(error,result){ console.log(result); client.close(); }); });

Related

How to fetch just the "_id" field from MongoDB find()

I wish to return just the document id's from mongo that match a find() query.
I know I can pass an object to exclude or include in the result set, however I cannot find a way to just return the _id field.
My thought process is returning just this bit of information is going to be way more efficient (my use case requires no other document data just the ObjectId).
An example query that I expected to work was:
collection.find({}, { _id: 1 }).toArray(function(err, docs) {
...
}
However this returns the entire document and not just the _id field.
You just need to use a projection to find what ya want.
collection.find({filter criteria here}, {foo: 0, bar: 0, _id: 1});
Since I don't know what your document collection looks like this is all I can do for you. foo: 0 for example is exclude this property.
I found that using the cursor object directly I can specify the required projection. The mongodb package on npm when calling toArray() is returning the entire document regardless of the projection specified in the initial find(). Fixed working example below that satisfies my requirements of just getting the _id field.
Example document:
{
_id: new ObjectId(...),
test1: "hello",
test2: "world!"
}
Working Projection
var cursor = collection.find({});
cursor.project({
test1: 0,
test2: 0
});
cursor.toArray(function(err, docs) {
// Importantly the docs objects here only
// have the field _id
});
Because _id is by definition unique, you can use distinct to get an array of the _id values of all documents as:
collection.distinct('_id', function(err, ids) {
...
}
you can do like this
collection.find({},'_id').toArray(function(err, docs) {
...
}

ObjectID with mongoskin

Why does this query not work in Mongoskin? (where itemID is a Mongo ObjectID)
{"_id": itemID}
I know that there is truly an element that has a matching _id because if I run this same query through the MongoDB shell it works. Why doesn't it work with Mongoskin?
var ObjectId = require('mongodb').ObjectID;
Notice: the name of the factory function is ObjectID, instead of ObjectId
Then you can use:
db.collection('XXX').update({_id: ObjectId(XXX)}, {$set: {XXX : XXX}});
Well, db is a wrapped function of mongoskin:
module.exports = (function() {
return require('mongoskin').db('mongodb://localhost:27017/db_name');
})();
It turns out that mongoskin uses a different type of ObjectID than vanilla mongoDB. I was using another library to convert my string to an ObjectID, hence the confusion. Here's what worked for me to get the proper ObjectID object:
require('mongoskin').ObjectID.createFromHexString(hexString);

Cannot remove on mongodb using mongoose?

Hi im trying to simply remove a document from a collection using mongoose but for some strange reason I cannot get it to work.
Here is the code:
function deleteUserevent()
{console.log('in delete User Event');
models.Userevent.remove({ _id: "5214f4050acb53fe31000004"}, function(err) {
if (!err){
console.log('deleted user event!');
}
else {
console.log('error');
}
});
}
Can anyone help me out on my syntax? I know the _id is stored as new ObjectId("5214f4050acb53fe31000004") but I have tried this with no joy?
Thanks.
In MongoDB, the "_id" field of documents is of type ObjectId, as you mentioned. This is not equal to a String, so running the query
db.userevent.remove({ _id: "5214f4050acb53fe31000004"});
will not match anything, and will not remove anything. Instead, you must search for a document where the _id field is an ObjectId with that value:
db.userevents.remove({ _id: ObjectId("5214f4050acb53fe31000004")});
In mongoose, you can use the findByIdAndRemove command to remove a document with a specific _id. This command takes either an ObjectId or a String as an argument, so
query = Userevent.findByIdAndRemove("5214f4050acb53fe31000004");
should work just fine.
Just add exec() after query.
It should work like this:
await models.Userevent.findByIdAndDelete("5214f4050acb53fe31000004").exec()

Upserts in mongodb when using custom _id values

I need to insert a document if it doesn't exist. I know that the "upsert" option can do that, but I have some particular needs.
First I need to create the document with its _id field only, but only if it doesn't exist already. My _id field is a number generated by me (not an ObjectId). If I use the "upsert" option then I get "Mod on _id not allowed"
db.mycollection.update({ _id: id }, { _id: id }, { upsert: true });
I know that we can't use the _id in a $set.
So, my question is: If there any way to a "create if doesn't exists" atomically in mongodb?
EDIT:
As proposed by #Barrie this works (using nodejs and mongoose):
var newUser = new User({ _id: id });
newUser.save(function (err) {
if (err && err.code === 11000) {
console.log('If duplicate key the user already exists', newTwitterUser);
return;
}
console.log('New user or err', newTwitterUser);
});
But I still wonder if it is the best way to do it.
I had the same problem, but found a better solution for my needs. You can use that same query style if you simply remove the _id attribute from the update object. So if at first you get an error with this:
db.mycollection.update({ _id: id }, {$set: { _id: id, name: 'name' }}, { upsert: true });
instead use this:
db.mycollection.update({ _id: id }, {$set: { name: 'name' }}, { upsert: true });
This is better because it works for both insert and update.
UPDATE: Upsert with _id can be done without $setOnInsert, as explaind by #Barrie above.
The trick is to use $setOnInsert:{_id:1} with upsert, that way the _id is only written to if it's an insert, and never for updates.
Only, there was a bug preventing this from working until v2.6 - I just tried it on 2.4 and it's not working.
The workaround I use is having another ID field with a unique index. Eg. $setOnInsert:{myId:1}.
You can just use insert(). If the document with the _id you specify already exists, the insert() will fail, nothing will be modified - so "create if it doesn't exist" is what it's already doing by default when you use insert() with a user-created _id.
Please note that $setOnInsert don't work easily when you upsert a simple key => value object (not $set or other).
I need to use that (in PHP):
public function update($criteria , $new_object, array $options = array()){
// In 2.6, $setOnInsert with upsert == true work with _id field
if(isset($options['upsert']) && $options['upsert']){
$firstKey = array_keys($new_object)[0];
if(strpos($firstKey, '$')===0){
$new_object['$setOnInsert']['_id'] = $this->getStringId();
}
//Even, we need to check if the object exists
else if($this->findOne($criteria, ['_id'])===null){
//In this case, we need to set the _id
$new_object['_id'] = $this->getStringId();
}
}
return parent::update($criteria, $new_object, $options);
}

Identify last document from MongoDB find() result set

I'm trying to 'stream' data from a node.js/MongoDB instance to the client using websockets. It is all working well.
But how to I identify the last document in the result? I'm using node-mongodb-native to connect to MongoDB from node.js.
A simplified example:
collection.find({}, {}, function(err, cursor) {
if (err) sys.puts(err.message);
cursor.each(function(err, doc) {
client.send(doc);
});
});
Since mongodb objectId contatins creation date you can sort by id, descending and then use limit(1):
db.collection.find().sort( { _id : -1 } ).limit(1);
Note: i am not familiar with node.js at all, above command is mongo shell command and i suppose you can easy rewrite it to node.js.
Say I have companies collection. Below snippet gives me last document in the collection.
db.companies.find({},{"_id":1}).skip(db.companies.find().count()-1);
Code cannot rely on _id as it may not be on a specific pattern always if it's a user defined value.
Use sort and limit, if you want to use cursor :
var last = null;
var findCursor = collection.find({}).cursor();
findCursor.on("data", function(data) {
last = data;
...
});
findCursor.on("end", function(data) {
// last result in last
....
});