Can't create a collection in MongoDB datatbase - node.js

Using this code to create a collection on MongoDB database hosted on mlab. But somehow it does not seems to be working. Is there something I am missing in this code? .save() function does not seem to be firing at all. Can it be due to my schema?
var mongoose= require('mongoose');
var Schema= mongoose.Schema;
app.use(express.static(__dirname+'/views'));
app.use(express.static(path.join(__dirname, 'public')));
//connect to mongo db database
mongoose.connect('mongodb://blaa:blaa#ds127132.mlab.com:27132/vendor');
//vendor schema
var vendorSchema= new Schema({
name:String,
image: { data: Buffer, contentType: String },
vendortype:String,
location: {
type: [Number], // [<longitude>, <latitude>]
index: '2d' // create the geospatial index
},
contactinfo:String,
description:String
});
//creating a model for mongoDB database
var Vendor= mongoose.model('Vendor',vendorSchema);
//just putting a sample record data
var imgPath = 'public/images/background.jpg';
var one = Vendor({
name: 'Justin Motor Works',
vendortype: 'Automobile',
contactinfo:'6764563839',
location: {
type:[23.600800037384033,46.76758746952729]
},
image: {
data: fs.readFileSync(imgPath),
contentType: 'image/jpg'
},
description: 'Motor workshop'
}).
save(function(err){
if(err)
throw err;
else {
console.log('create record failed');
}
});

mongoose.connect is an asynchronous function, you need to put your code inside a callback or promise.then(function(){.
Try this:
mongoose.connect('mongodb://blaa:blaa#ds127132.mlab.com:27132/vendor', function(error) {
if (error)
//handle error
//Your code
});
Or this:
mongoose.connect('mongodb://blaa:blaa#ds127132.mlab.com:27132/vendor').then(
() => {
//Your code
},
err => {
//Your error handling
}
);
Notice the error handling, it's important to know what caused the error for future debugging.
Also change the JSON structure of location when you are saving it as #NeilLunn said in the comments to something like this:
location: [23.600800037384033,46.76758746952729],
type in mongoose means actually defining the type of the key, and not a nested type key.

Related

Node.JS Express 4 - Mongoose Does not saving data

I am trying to save a data in MongoDB with Mongoose with Express.JS 4 and Bluebird.
What I have done is like this-
bin/www
var mongoose = require('mongoose');
mongoose.Promise = require('bluebird');
.......
.......
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function()
{// successfully connected!
console.log("Successfully Connected to Mongo-DB");
});
And getting this in console-
Successfully Connected to Mongo-DB` - So, MongoDB connected successfully
models/post.js
var mongoose = require('mongoose');
var postSchema = new mongoose.Schema({
created_by: String, //should be changed to ObjectId, ref "User"
created_at: {type: Date, default: Date.now},
text: String
});
module.exports = mongoose.model('Post', postSchema);
app.js
var Post_Data = require("./models/post");
....
....
router.get('/', function(req, res, next)
{
var Post = mongoose.model("Post");
var post = new Post({
created_by: ""+Math.random()
});
console.log( Post.create(post) );
res.render(
'index',
{
title : 'Express',
site_name : 'Our Site',
layout : 'templates/layout'
}
);
});
And after that I am getting this in console-
Promise {
_bitField: 0,
_fulfillmentHandler0: undefined,
_rejectionHandler0: undefined,
_promise0: undefined,
_receiver0: undefined }
But, nothing is saved, a proof for that is -
I am finding this-
After using MongoBooster.
Update-
My DB config is like this-
"MONGO_URI": "mongodb://localhost:27017/express_test",
"MONGO_OPTIONS": {
"db": { "safe": true },
"name":"express_test"
}
So, can anyone please help, why it is not saving anything?
Thanks in advance for helping.
The .create() function is a shortcut for new Model and .save(). You are trying to .create an instance of Model rather than a simple Object. See Constructing documents in Mongoose's Models documentation for their quick example.
The return from a Mongoose data function is just the promise of an asynchronous task to be run in the future, logging that is largely pointless. Use .then() to wait until the promise has been resolved.
Error handling is missing from your code as well, something could be getting thrown there. Use a .catch() for promise error handling.
Post.create({ created_by: ""+Math.random() })
.then(function (result) {
console.log('Saved' result)
})
.catch(function (err) {
console.error('Oh No', err)
})
All of this can be done with callbacks (like the Mongoose docco examples) but promises, particularly bluebird promises are nicer.
I just use this syntax combination to create and save my model:
var myPage = new LandingPage({
user:req.user,
slug: req.body.slug,
}).save(function(err,savedModel){
if(!err){
console.log(savedModel);
}
});
You are calling the wrong model in your app.js module as you are importing the model as
var Post_Data = require("./models/post"); // <-- Post_Data model never used
....
....
but creating a new Post model instance in your router implementation as
var Post = mongoose.model("Post"); // <-- different model
var post = new Post({
created_by: ""+Math.random()
});
You need to call and use the correct models. So I would suggest you re-write your app.js module to use the save() method as:
var Post = require("./models/post"); // <-- import correct Post model
....
....
router.get('/', function(req, res, next) {
var post = new Post({ created_by: ""+Math.random() });
post.save().then(function(post) {
console.log(post); // <-- newly created post
res.render('index', {
title: 'Express',
site_name: 'Our Site',
layout: 'templates/layout'
});
})
.catch(function(err) {
console.error('Oopsy', err);
});
});
if you store post schema in a variable by require then can use that variable.
var Post_Data = require("./models/post");
so can use new Post_Data no need to use var Post = mongoose.model("Post"); because you have already exported this schema module.exports = mongoose.model('Post', postSchema);
you can try this one :
var Post_Data = require("./models/post");
router.get('/', function(req, res, next)
{
var post = new Post_Data({created_by: ""+Math.random()});
post.save(function(error, data) {
if(error) {
return res.status(500).send({error: 'Error occurred during create post'});
}
return res.render('index',{
title : 'Express',
site_name : 'Our Site',
layout : 'templates/layout'
});
});
});
So it's true that if you're creating a document in memory by calling new Post(values) that you will save it with post.save(cb); rather than 'Post.create(post);, but I'm thinking that the underlying issue (though this isn't easy to be certain of based on the code you're showing) is that you're connecting with the MongoDB driver, rather than mongoose itself. Yourdb` variable isn't shown to be declared in the code you posted, so I'm making it an assumption.
That said, if I'm right, you need to call mongoose.connect or mongoose.createConnection in order for Mongoose to know it's connected to the db and save documents to it. You can pass an existing connection to mongoose, so if you're already doing so then I apologize for my erroneous assumption.

How to perform Update and Delete operations in a bucket using Couchbase and Nodejs sdk

I am moving from mongodb to Couchbase using Node.js. I want to perform the CRUD operations. Insert(create) and Get are working fine, but when I want to perform Update and Delete getting some error messages (Here update purpose using 'upsert','replace' are used) like:
TypeError: Cannot read property 'replace' of undefined
Here is code:
db.js
// Instantiate Couchbase and Ottoman
var couchbase=require('couchbase');
var ottoman=require('ottoman');
// Build my cluster object and open a new cluster
var myCluster = new couchbase.Cluster('localhost:8091');
var myBucket = myCluster.openBucket('default');
ottoman.bucket=myBucket;
require('./model/user');
ottoman.ensureIndices(function(){});
user.js
var db = require('./../db.js').myBucket;
var ottoman = require('ottoman');
var userMdl = ottoman.model('User', {
firstName: {type:'string'},
lastName: {type:'string'},
created: {type: 'Date', default:function(){return new Date()}},
email:'string',
phone: 'string'
},{
index: {
findByID: {
by: '_id'
},
}
})
module.exports = userMdl;
routes.js
var bodyParser = require('body-parser');
var db = require('../schema/db').myBucket;
var user=require('../schema/model/user');
var jsonParser = bodyParser.json();
var urlencodedParser = bodyParser.urlencoded({ extended: false });
module.exports = function (app) {
// Delete a record
app.post("/api/delete/:_id", function(req, res) {
console.log("_id:"+req.params._id)
if(!req.params._id) {
return res.status(400).send({"status": "error", "message": "A document id is required"});
}
db.delete({_id:req.params._id}, function(error, result) {
if(error) {
return res.status(400).send(error);
}
res.send(result);
});
});
app.post('/api/user/update/:id',function(req,res){
db.replace(req.params.id,{firstName:"Mahesh"},function(err,result){
if (err) {
res.status = 400;
res.send(err);
return;
}
else {
res.status = 202;
res.send(result);
}
})
})
}
I am stuck here from last two days.
You missed one argument although it can be optional.
From Couchbase Node.js SDK document, it have 4 arguments, but you have only 3.
db.replace(req.params.id,{firstName:"Mahesh"},function(err,result){
=>
db.replace(req.params.id,{firstName:"Mahesh"}, {}, function(err,result){
With 3rd argument of empty map may work properly, but notice that Couchbase uses optimistic locking, so you require "CAS" value for original document when you modify the original to get data integrity.
the line in db.js var ottoman = require('ottoman');it's a constructor itself. Then you have two instances, and the error comes in user.js when you try to define a model, because node-ottoman needs a reference to the bucket.
You should assign the bucket in the user.js or reuse the ottoman object that you left in the db.js
model.js
// Instantiate Couchbase and Ottoman
var couchbase = require('couchbase');
var ottoman = require('ottoman');
// Build my cluster object and open a new cluster
var myCluster = new couchbase.Cluster('localhost:8091');
var myBucket = myCluster.openBucket('default');
ottoman.bucket = myBucket;
var userMdl = ottoman.model('User', {
firstName: {type:'string'},
lastName: {type:'string'},
created: {type: 'Date', default:function(){return new Date()}},
email:'string',
phone: 'string'
},{
index: {
findByID: {
by: '_id'
},
}
}) ;
// this line needs to be after you define the model
ottoman.ensureIndices(function(){});
module.exports = userMdl;
model.exports = mybucket;
You can update Couchbase document using 2 ways 1st by upsert method and second by N1qlQuery
bucket.upsert('user', {'name': 'Jay'}, {'expiry': 1}, function(err){
bucket.get('user', function(err, result) {
console.log('Have item: %j', result.value);
})
});
let query = N1qlQuery.fromString("UPDATE `"+BUCKETNAME+"` SET name='"+data.name+"' where _id ='"+id+"'");
bucket.query(query,(error,result)=>{
if(error){
console.log(error);
}
console.log(result);
});
You can delete Couchbase document using 2 ways 1st is removed method and second by N1qlQuery
bucket.remove(id, function(error, result) {
console.log("Deleted");
});
let query = N1qlQuery.fromString("DELETE FROM `"+BUCKETNAME+"` WHERE _id = '"+id+"'");
bucket.query(query,(error,result)=>{
if(error){
console.log(error);
}
console.log(result);
})

Mongoose: Is it possible to set strict:false after defining the schema, like through a middleware or a plugin?

When you define a schema in Mongoose you have an option to set {strict:false}
Is there an option to have that set after you've defined the schema? Like through a mongoose middleware or a mongoose plugin?
I want to create a plugin which will need to store some additional data into the database, which I wouldn't be able to unless the plugin user has either set {strict:false} or added the fields that I would want to store data in their schema themselves, both of which are unlikely. So I was wondering if there's a way for me to make that happen from my plugin code itself?
Mongoose is an ODM, and the {strict: true} option in this regard only applies to queries you run through Mongoose, it's not enforced in the mongoDB side, your documents remain schemaless.
But you don't have to use mongoose to make all of your queries, you can use the native mongoDB driver underneath in order to bypass all of that. Mongoose even gives you a shortcut to do so in the form of Model.collection. Here's an example:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var PersonSchema = new Schema({
name: String
}, {
strict: true
});
var Person = mongoose.model('Person', PersonSchema);
mongoose.connect('mongodb://localhost/test', function(err) {
if (err) {
throw err;
}
Person.collection.insert({
name: 'Bill',
extraProp: 'Hello World'
}, function(err, result) {
if (err) {
throw err;
}
console.log(result);
});
console.log('Connected');
});
Edit:
You can disable strict for specific model paths. I think this is more what you're looking for.
PersonSchema.pre('save', function(next) {
this.set('extraProp', 'hello', {
strict: false
});
next();
});
Just an FYI, what I ended up doing was creating a sub-schema, then disabling strict in there..
I was doing this for meta data, which is unstructured, so heres my example:
module.exports = Mongoose => {
const Schema = Mongoose.Schema
const metaSchema = new Schema({},{ strict: false })
const modelSchema = new Schema({
title: Schema.Types.String,
metaData: metaSchema
})
modelSchema.statics.createMeta = function( title, meta, cb ) {
return new this({
title: title,
metaData: meta
}).save()
}
return Mongoose.model( 'Foobar', modelSchema )
}
Then to use it:
Foobar.createMeta( 'blah blah', {
foo: 'AA',
bar: 'BB'
} )
.then( data => console.log( '# RESULT:', data ) )
.catch( err => console.error( 'ERROR:',err ) )
Which seems to work fine :)

Mongoose save callback doesn't fire

I'm new to mongoose and I'm having a hard time finding the issue within my code. I'm building a REST server using Sails.js and Mongoose. I have a node module (e.g. "sails-mongoose") for exporting mongoose, where I also connect to my database:
var mongoose = require('mongoose');
mongoose.connect('mongodb://#localhost:27017/fooria');
module.exports = mongoose;
And in my model.js:
var adapter = require('sails-mongoose');
var schema = new adapter.Schema({
firstname: {
type: String,
required: true,
trim: true
}
});
module.exports = {
schema: schema,
model: adapter.model('Collection', schema)
}
In my controller's create method I have:
create: function(req, res, next) {
var userData = {firstname: 'Test'};
var users = new Users.model(userData);
users.save(function(err, data){
if (err) return res.json(err, 400);
res.json(data, 201);
});
}
When running create method, the entry is saved to the Mongodb collection but the callback is never reached. Can someone please help me on this track, as I found similar questions but none helped me though. Thanks!
I suppose your are using Express. According Express docs you are calling res.json using incorrect parameters (wrong order).
Correct format:
res.json(code, data)
Example:
res.json(500, { error: 'message' })

Mongoose findOne function not being executed

... (... = some unrelated code)
var mongoose = require('mongoose');
var db = mongoose.connect('mongodb://localhost/test');
...
dataSchema = new Schema({
'url': { type: String, index: true },
'user_id': { type: Schema.ObjectId, index:true }
});
var Website = mongoose.model('websites', dataSchema);
...
Website.findOne({url: "someurl.com"},function (err, docs) {
console.log(docs._id);
});
...
For some reason the console.log does not execute. Is there anyway to tell if I am setting up my schema correctly or see if my find function failed or any sort of indication of where the problem might be? Currently, when I run my script, no errors occur, but nothing is printed out either.
Thanks!
You can check for connection and schema errors by hooking the error event on the connection as:
mongoose.connection.on('error', function(err) {
console.error('MongoDB error: %s', err);
});

Resources