I have following code:
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/test')
var Schema = mongoose.Schema;
var schema = new Schema({name : String, inventory: {}});
var Character = mongoose.model('Character',schema);
var Frodo = new Character({name: 'Frodo',inventory:{ringOfPower: 1}});
Frodo.save();
Character.findOne({name : 'Frodo'},function(error, character){
console.log(character);
});
I am running it as node optionminimize.js and null is getting logged to the console.It got persisted in mongodb alright, I opened a mongodb shell and ran
db.characters.findOne({name:'Frodo'})
and get following result:
{
"_id" : ObjectId("582fc3bab386f00ed0e7fede"),
"name" : "Frodo",
"inventory" : {
"ringOfPower" : 1
},
"__v" : 0
}
Why the document parameter in the callback is receiving null?
Frodo.save() is a async call so it returns a Promise, and you search by Charachter.findOne immediately the line after which happens before the Frodo.save() promise is resolved.
So, the search must be executed after the character is saved successfully, otherwise it returns null as you mentioned, so your code need to be like this:
Frodo.save()
.then(function() {
Character.findOne({name : 'Frodo'}, function(error, character) {
console.log(character);
});
})
Related
I am using MongoDB for the first time and I came across an error that I could not solve.
Here is my code:
const mongoose = require('../../common/services/mongoose.service').mongoose;
const Schema = mongoose.Schema;
const functions = require('./functions');
const userSchema = new Schema({
email: String,
password: String,
number: String,
state: Boolean
});
userSchema.virtual('id').get(function () {
return this._id.toHexString();
});
// Ensure virtual fields are serialised.
userSchema.set('toJSON', {
virtuals: true
});
userSchema.findById = function (cb) {
return this.model('Users').find({id: this.id}, cb);
};
const User = mongoose.model('Users', userSchema);
exports.findByEmail = (email) => {
//console.log('hello'); //this works btw
return User.find({email: email});
};
So in the code above, findByEmail works fine since hello is logged. However, when it gets to return User.find, I get this error: SyntaxError: Unexpected token g in JSON at position 0.
This is what is currently in the DB:
{
"_id" : ObjectId("6026b813f1828a51f8979616"),
"email" : "gogo#gmail.com",
"password" : "GLImDln1xMKfKS/E99s8qg==$Es3PIHD95vV89973Xq4RecveYMEf22PCH/pFtG1+xq4Gtc4DelA/JXlRNcOR11Rfv/J1uaZCuOplsEmHhY0ehQ==",
"number" : "6969",
"state" : true,
"__v" : 0
}
I input gogo#gmail.com. Does anyone know what I am doing wrong? It would mean a lot to me. I am using node/vue btw.
Error occurs within findByEmail when I run it
I have already seen the discussion about the following question with a similar title
mongoose 'findById' returns null with valid id
But my problem is not the database name since all my other connections with the same database in fact the queries on the same collection are working fine.
I am using mongoose 4.13.6, node js 6.11 and mongo 3.4.
It is a post request .
var query=req.body;
I am sending the search parameters as
var findFruit =
{
_id:query._id
}
When I print my findFruit I get :
_id:'5a1cf77920701c1f0aafb85e'
The controller function for this is :
Fruit.findById(findFruit._id,function(err,fruit){
if( _.isNull(err) ){
var response = genRes.generateResponse(true,"found successfully");
callback(response);
}
else{
var response = genRes.generateResponse(false,"there occured some error : "+err);
callback(response);
}
})
I even tried find
Fruit.find(findFruit,function(err,fruit){
if( _.isNull(err) ){
var response = genRes.generateResponse(true,"found successfully");
callback(response);
}
else{
var response = genRes.generateResponse(false,"there occured some error : "+err);
callback(response);
}
})
The collection for sure has the entry under this id .
I went through this git issue as well https://github.com/Automattic/mongoose/issues/3079
Unfortunately I cannot downgrade mongoose as it might affect multiple other working functions.
Edit :
I tried creating ObjectId like :
var mongoose = require('mongoose');
var ObjectID = require('mongodb').ObjectID;
var objectId = new ObjectID();
// Convert the object id to a hex string
var originalHex = objectId.toHexString();
// Create a new ObjectID using the createFromHexString function
var newObjectId = new ObjectID.createFromHexString(query._id);
The model file :
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ObjectId = Schema.ObjectId;
var FruitSchema = new Schema({
name : {type : String, unique : true},
color : {type : String}
});
module.exports = mongoose.model('Fruit', FruitSchema);
All my findById("id") calls returned null.
When looking at the collection with Compass I realized that all my _id elements were Strings. Note that the entire collection was imported.
I created a new element in Compass and the _id was created as ObjectId! and when I called findById("id") with that element's id it worked!
My conclusion is that there is obviously a bug with import. I have not found a way to convert the string _id fields to ObjectId's in the actual collection.
All my findById("id") calls returned null, when _id elements are Strings.
In the first place:
Check your mongodb database, if _id is stored as String, findById(id) can not find since it identifies ObjectId. If you've used import database by using mongoimport command and including _id in JSON:
Solution 1:
modify your JSON and for each document, change _id for instance:
_id: "5a68fde3f09ad7646ddec17e" to the following and run mongoimport again:
"_id": { "$oid": "5a68fde3f09ad7646ddec17e" }
Solution 2:
delete _id in the JSON file, drop collection and import again. Mongo will auto-create _id.
After any of solutions above, findById("id") will work.
Secondly:
Specifically in such cases where your _id elements are string, might be a better idea to use mongodb package: npm i mongodb
var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://localhost:27017/";
MongoClient.connect(url, function (err, db) {
if (err) throw err;
var dbo = db.db("your_db_name");
dbo.collection("fruits_collection")
.find({_id:'5a1cf77920701c1f0aafb85e'})
//.find({_id:'5a1cf77920701c1f0aafb85e'}, { projection: { _id: 0, name: 1, color: 1} }) // to select specific columns desired
.toArray(function (err, result) {
if (err) throw err;
console.log(result);
db.close();
});
});
The above simple code, assumed you manage error handling yourself, either through try-catch, or
sending 404 as status code, or redirect to error page template, depending on whether the code is embedded in the Express route handler or not.
Hope this helped .. :)
Still trying to figure out why findById didn't work for me but the following piece of code did it
var mongoose = require('mongoose');
var newObjectId=new mongoose.Types.ObjectId(query._id);
var params={
'_id':newObjectId
}
Fruit.find(params).exec(function (err,fruit) {
if( _.isNull(err) ){
var response = genRes.generateResponse(true,"found successfully");
callback(response);
}
else{
var response = genRes.generateResponse(false,"there occured some error : "+err);
callback(response);
}
})
#Shoom. Yes, worked for me, thanks. findById() expects ObjectID, not a String.
I did not have a constraint to create documents with a specific id, so I imported with no _id. The db had newly-assigned _id as ObjectID.
findById(id), (and updateOne({ _id: id }, ...), started working as expected.
I have set up a Express REST Api and would like to Implement a task that checks if a certain Object ID exists.
If that ID exists in the Mongo Database I want to update this Document using a Put Request. This Part already works in my code.
IF the ID does not yet exist in the database I would like to create a new Document. To do this I tried to set the "upsert" option to true, But If I now make a put request to a ID, which isn't in my DB yet it comes back with the error:
throw er; // Unhandled 'error' event
^
CastError: Cast to ObjectId failed for value "34455ab67" at path "_id" for model "event"
Here is my Code for the event model:
var mongoose = require('mongoose');
var eventSchema = mongoose.Schema({
name: {
type: String,
required: true
}
});
var Events = module.exports = mongoose.model('event', eventSchema, 'event');
module.exports.updateEvent = function (id, event, options, callback) {
var query = {_id : id};
var update = {
name: event.name,
};
Events.findOneAndUpdate(query, update, options, callback);
};
This is the REST API Call
app.put('/api/event/:_id', function(req, res) {
var id = req.params._id;
var event = req.body;
var options = {
upsert: true,
new: true,
setDefaultsOnInsert: true
};
Events.updateEvent(id, event, options, function(err, event){
if(err){
trow err;
}
res.json(event);
})
});
Any help would be highly appreciated!
This error happened because you defined the event schema without "_id",so the type of "_id" property by default become "ObjectId" and then when you tried to send "_id" with this value "34455ab67" mongoose method tried to cast it to "ObjectId" type but it's invalid string. so you should do the following:
Send valid string values for the "_id" property.
Validate the input string before converting it to "ObjectId".
If the input string is valid,convert it to "ObjectId" then use it in
the mongoose queries.
Check the following example:
var mongoose = require('mongoose');
//inputId is the input string passed from the front end
if (inputId.match(/^[0-9a-fA-F]{24}$/)) {
// it's a valid string to be converted to "ObjectId"
var id = mongoose.Types.ObjectId(inputId);
//then use this id in your mongoose queries.
} else {
//Not valid
}
or you can define the "_id" with "String" type to simplify this process but that depends on your needs.
I've simple collection in mongo and a corresponding mongoose model. This collection will only contain one document always. When I run a query in mongoshell it is giving me the result, but when I try to do findOne using mongoose it is not returning any result at all. Can someone help me figure out what is wrong. Below is my code.
Model:
const mongoose = require('mongoose');
const schema = new mongoose.Schema({
lastResetMonth: {
type: Number
},
lastResetWeek: {
type: Number
},
currentFisYear:{
type: Number
}
});
module.exports = mongoose.model('ReserveResetTrack', schema, 'reserveResetTrack');
const ReserveResetTrack = require('../models/ReserveResetTrack');
ReserveResetTrack.findOne({})
.then(trackData => {
return {
lastFisMonth: trackData.lastMonth,
lastFisWeek: trackData.lastWeek
}
});
The above code is always returning nothing but a promise.
This is the only document i've in my collection and this will be the only one for ever
{
"_id" : ObjectId("589271a36bfa2da821b13ce8"),
"lastMonth" : 0,
"lastWeek" : 0,
"currentYear" : 0
}
Use exec() like this:
ReserveResetTrack.findOne({})
.exec() // <--- use exec() here
.then(trackData => {
return {
lastFisMonth: trackData.lastMonth,
lastFisWeek: trackData.lastWeek
}
});
i have mongoose schema named administrator
var administratorSchema = new mongoose.Schema({
username : String,
password : String,
active : Boolean,
level : String
});
When i try this query,i can get the result
mongoose.connect('mongodb://'+dbServer+'/'+dbName, function(connectionError) {
var administratorModel = mongoose.model('administrators',administratorSchema);
administratorModel.findOne({_id,111155dffxv}function(err, resad){
console.log('into mongoose findone');
});
});
====> Console output : 'into mongoose findone'
The problem is : when i try to change the criteria from _id to "username", mongoose dosen't work and findOne dosen't execute:
mongoose.connect('mongodb://'+dbServer+'/'+dbName, function(connectionError) {
var administratorModel = mongoose.model('administrators',administratorSchema);
administratorModel.findOne({'username','mohamed'}function(err, resad){
console.log('into mongoose findone');
});
});
====> Console output : ''
Thanks.
Your query object isn't valid (use a colon instead of a comma) and you're missing a comma between the findOne parameters. Your call should look like this instead:
administratorModel.findOne({'username': 'mohamed'}, function(err, resad){
console.log('into mongoose findone');
});
You should also be checking the err parameter of your callbacks to see if things are working.
Not sure why it was reaching the callback with your _id criteria version as that one has the same issues.