ObjectID with mongoskin - mongodb

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);

Related

Why Bulk update operation is not working if i passes _id in matching condition using Mongoose?

I am facing a problem while using bulk update operation in mongoose. Whenever i passes _id in matching condition. it will not updated the result and when i changed my condition criteria besides _id, It works fine. Any idea about that. Please help me. Here is my code
var bulk = roleObj.collection.initializeUnorderedBulkOp();
bulk.find({_id: '56b9ba46b51a3b2114b0b44e'}).update({$set: {name: 'bla bla'}});
bulk.execute(function (err, data) {
});
This is because you are calling the underlying mongo collection's bulk methods, not the mongoose API methods which automatically wrap the string _ids for you in ObjectID. You need to cast the string to ObjectID first then use it in your bulk update:
var mongoose = require('mongoose'),
id = mongoose.Types.ObjectId('56b9ba46b51a3b2114b0b44e');
bulk = roleObj.collection.initializeUnorderedBulkOp();
bulk.find({_id: id}).update({$set: {name: 'bla bla'}});
bulk.execute(function (err, data) { ... });

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()

Mongoose query return null

I can't seem to get a response from mongodb. I am using node.js and mongodb with the help of mongoose.
In my node.js app I have
mongoose.connect('mongodb://localhost:27017/myDB');
var Schema = mongoose.Schema,
ObjectId = Schema.ObjectId;
var BlogPost = new Schema({
author : ObjectId,
title : String,
slug : { type: String, lowercase: true, trim: true },
content : String,
summary : String,
date : Date
})
var BlogModel = mongoose.model('BlogPost', BlogPost);
BlogModel.find({}, function(docs){
console.log(docs);
});
If I type show dbs in the mongo shell I get
admin (empty)
myDB 0.203125GB
local (empty)
test (empty)
db.blogmodel.find() returns :
{ "_id" : ObjectId("50108d3df57b0e3375a20479"), "title" : "FirstPost" }
and yes I do have mongod running.
Fixed Solution
var BlogModel = mongoose.model('blogmodel', BlogPost, 'blogmodel');
It works because its (model name, schema name, collection name)
Mongoose pluralizes model names so it's running find on the "blogposts" collection instead of "blogpost". That said, your query in the mongo shell is on the "blogmodel" collection. In that case:
var BlogModel = mongoose.Model("BlogModel", ..)
or pass the collection name as the third param:
var BlogModel = mongoose.model("BlogPost", schema, "blogmodel")
The first parameter to your BlogModel.find callback is err, the second parameter is docs. So your code should be:
BlogModel.find({}, function(err, docs){
console.log(docs);
});
For anyone still experiencing this issue even after checking the accepted answer – make sure your database connection url contains the database name, e.g. for database name myDB...
mongoose.connect(`mongodb://localhost:27017/myDB`)
I'd forgotten it and my mongoose searches were all returning null or empty arrays.
I experienced similar error yesterday, in my case error was caused by data imported to mongo. After I used mongoimport key _id was stored as string instead of ObjectId. When I was querying data in mongo everything works well, but in Mongoose when I was trying find something by _id it always returned null or empty Array. I hope that info might by useful for someone.

mongoose (mongodb) Alias _id field

Is it possible with mongoose use a different name, in my case uppercase 'ID', as an alias for the schema _id field?
Would I need to add a virtual or is there another way of setting this up?
Any help gratefully received thanks.
You would use a virtual attribute for that. As in:
yourSchema.virtual('ID').get(function() { return this._id; });
The easiest way is to specify alias in the schema:
let s = new Schema({
_id: { type: String, alias: "ID" }
});
This automatically creates both getter and setter, so it is possible to use ID everywhere instead of _id.
Mongoose documentation on aliases
Based on v5.11.9 mongoose documentation looks like mongoose assigns each of your schemas an id virtual getter by default which returns the document's _id field

Finding an Embedded Document by a specific property in Mongoose, Node.js, MongodDB

For this app, I'm using Node.js, MongoDB, Mongoose & Express
So I have a Param Object that contains an array of Pivots, and I want to read certain data from the pivots as outlined below
---in models.js-------------------------
var Pivot = new Schema({
value : String
, destination : String
, counter : Number
});
var Param = new Schema({
title : String
, desc : String
, pivots : [Pivot]
});
------------- in main.js --------------
var Param = db.model('Param');
app.get('/:title/:value', function(req, res){
Param.findOne({"title":req.param('title')}, function(err, record){
console.log(record.pivots);
record.pivots.find({"value":req.param('value')}, function(err, m_pivot){
pivot.counter++;
res.redirect(m_pivot.destination);
});
record.save();
});
});
I know that the code works until console.log(record.pivots), since i got a doc collection with the right pivot documents inside.
However, there does not seem to be a find method to let me match an embedded document by the 'value' property defined in the schema. Is it possible to search through this array of embedded documents using .find() or .findOne() , and if not, is there some easy way to access it through mongoose?
varunsrin,
This should do it
app.get('/:title/:value', function(req, res) {
Param.findOne({'pivots.value': req.param('value'), "title":req.param('title')}},
function(err, record) {
record.pivot.counter++;
res.redirect(m_pivot.destination);
record.save();
});
});
Note the pluralization of the query to match the field name in your schema
You can querying using embedded document properties like this:
{'pivot.value': req.param('value')}}
Update in response to comment:
app.get('/:title/:value', function(req, res) {
Param.findOne({'pivot.value': req.param('value'), "title":req.param('title')}},
function(err, record) {
record.pivot.counter++;
res.redirect(m_pivot.destination);
record.save();
});
});
I solved it temporarily using a simple for loop to parse the object array as follows:
for (var i=0; i <record.pivots.length; i++){
if (record.pivots[i].value == req.param('value')){
res.redirect(record.pivots.destination);
}
}
However, I still think that Mongoose must have a simpler way of interacting with embedded documents - and this loop is somewhat slow, especially when the number of embedded documents grows large.
If anyone has any suggestions for a faster way to search this object array either in js or with a mongoose function, please post below.
the biggest problem with this is that if your req has some fields empty (that should act as wildcard), you will not find anything since mongo tries to match empty params as well, so searching for {"user":"bob", "color":""} is not the same as {"user":"bob", "color":"red"} or {"user":"bob"}. this means that you have to first create a query object and filter out any unused parameters before you pass it in, and if you create a query object, you can no longer do something like "user.name=..." because mongo interperets this as an error since it does not first resolve the object literal into a string.
Any ideas on this problem?
ps. You'd think it would be easy enough to make an object like:
user.name="bob"; user.color:"green"; user.signup.time="12342561"
and then just use user as a query object :/
I think you are looking for the "$in" keyword?
As in:
{a: {$in: [10, "hello"]}}
source: MongoDB Queries CheatSheet