Mongoose query return null - mongodb

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.

Related

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

How to query against ObjectId when not in mongo shell

I'm working on paging functionality using a range query. I'm using this test query in the mongo shell:
> var params = {$query: {_id: {$lt: ObjectId("52b06166eff887999c6efbd9")}}, $orderby: {_id: -1}, $maxScan: 3}
> params
{
"$query" : {
"_id" : {
"$lt" : ObjectId("52b06166eff887999c6efbd9")
}
},
"$orderby" : {
"_id" : -1
},
"$maxScan" : 3
}
> db.events.find(params)
I'd like to be able to pass the serialized params object to a web service (as a URL query string). However, the ObjectId class is only available inside the shell. Is there a way to specify an ObjectId as part of a query when not in the shell? I've tried the following as the value of $lt without success:
'ObjectId("52b06166eff887999c6efbd9")'
'new ObjectId("52b06166eff887999c6efbd9")'
{"$oid" : "52b06166eff887999c6efbd9"}
Generally speaking, this abstraction is handled by whatever MongoDB driver you use. If you are using an actual driver, you can do queries on _id without using ObjectId()
Mongoose / Node.js Example:
People.find({ _id : "Valid ObjectID String" }, function(e, person) {
console.log(e, person);
});
If you do still need the ObjectId helper, generally you are able to reference it in whatever native driver you need.
What you are doing in your last examples is passing your objectId as a string (first two examples) or as a dictionary third example. So surely it does not work.
You can pass just a string '52b06166eff887999c6efbd9' as a parameter and then when you receive it you can construct normal ObjectId on the server. For example in php you can construct it in the following way new MongoId('your string');

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

DbRef with Mongoose - mongoose-dbref or populate?

I have the following 2 schemas:
Company Event:
var companyEventSchema = new Schema({
name : String,
description
date : Date,
attendees : [ { type : Schema.ObjectId, ref : 'Member' } ],
]});
And Member
var memberSchema = new Schema({
name : String,
emailAddress: String,
password :String,
created: { type: Date, default: Date.now }
});
Is the way i've ref'd Member from companyEventSchema correct?
I'm trying to do something a long the lines of a dbref.
I saw theres a separate project for that though... mongoose-dbref
However, the mongoose docs say the above provides "dbref like functionality"
Which would be more efficient?
You only need to use an actual DBRef (and mongoose-dbref) for the case where a field can contain ObjectIds that reference documents in potentially more than one collection. A DBRef is a tuple of an ObjectId, a collection name, and an optional database name.
Mongoose ref: fields, however, contain just an ObjectId and it's the Mongoose schema that defines what one collection the ObjectIds reference.
So Mongoose ref: fields are more efficient and should always be used unless you need the multi-collection reference support that DBRef provides.

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