How to get data from mongodb for dynamically created schema model - node.js

I am trying to get data from mongodb but could not. Because below the error is the reason.I have inserted data into mongodb by dynamically creating schema model.So I am not able to get data from mongodb.How to get data from mongodb for (dynamically creating schema) collection? Please help anyone.I have searched in google but no use.
MissingSchemaError: Schema hasn't been registered for model "Tea".
Use mongoose.model(name, schema) at Mongoose.model
createschema.js
const db = mongoose.createConnection(
"mongodb://localhost:27017/products", {
useNewUrlParser: true,
useUnifiedTopology: true
}
);
function dynamicModel(suffix) {
var collsName = suffix.charAt(0).toUpperCase() + suffix.slice(1);
var collsSmall = suffix.toLowerCase();
var newSchema = new Schema({
pid: {
type: String
},
product_name: {
type: String
},
product_price: {
type: Number
}
}, {
versionKey: false,
collection: collsSmall
});
try {
if (db.model(collsName)) return db.model(collsName);
} catch (e) {
if (e.name === 'MissingSchemaError') {
return db.model(collsName, newSchema, collsSmall);
}
}
}
module.exports = dynamicModel;
data.controller.js:
const mongoose = require('mongoose');
module.exports.getCollectionData = (req, res, next) => {
let collection = req.query.collection;
let tabledata = mongoose.model(collection); //Got MissingSchemaError
tabledata.find({}, function(err, docs) {
if (err) {
console.log(err);
return;
} else {
res.json({ data: docs, success: true, msg: 'Products data loaded.' });
}
})
}
//Create model
module.exports.newCollection = (req, res, next) => {
var collectionName = req.query.collectionName;
var NewModel = require(path.resolve('./models/createschema.model.js'))(collectionName);
NewModel.create({ }, function(err, doc) {});
}
db.js:
const mongoose = require('mongoose');
mongoose.connect(process.env.MONGODB_URI, (err) => {
if (!err) { console.log('MongoDB connection succeeded.'); } else { console.log('Error in MongoDB connection : ' + JSON.stringify(err, undefined, 2)); }
});
require('./createschema.model');
api call:
http://localhost:3000/api/getCollectionData?collection='Tea'

Try db.model instead of mongoose.model in function getCollectionData
Since you created the collection on that particular connection, you have to use the same connection to get the model as well.
const db = mongoose.createConnection(
"mongodb://localhost:27017/products", {
useNewUrlParser: true,
useUnifiedTopology: true
}
);
module.exports.getCollectionData = (req, res, next) => {
let collection = req.query.collection;
let tabledata = db.model(collection); //Change here
tabledata.find({}, function(err, docs) {
if (err) {
console.log(err);
return;
} else {
res.json({ data: docs, success: true, msg: 'Products data loaded.' });
}
})
}

You fundamentally misuse mongoose.model() / connection.model().
This function can ONLY be used to CREATE a NEW mongoose model using
required model name and schema deffinition parameters.
In createschema.js when you have try {if (db.model(collsName))
return db.model(collsName);} catch you are NOT checking if model
already exists. db.model(collsName) will always throw an error
because you are not providing second required parameter with schema
definition.
I presume you are trying to check if model already exists and if so
return it. Please see documentation for
Connection.prototype.models. the fragment above should
therefore be:
try {
// db is an instance of mongoose.Connection
let existingModel = db.models[collsName];
if (existingModel) return existingModel;
} catch
Likewise in data.controller.js getCollectionData currently you are
calling a method to create a new mongoose model 'mongoose.model()',
but don't provide a schema (hence why you get MissingSchemaError)
you need to EITHER
get the model from mongoose instance (if already registered as you seem to imply)
let tabledata = mongoose.connection.models[collection];
OR
create a new mongoose model
const dynamicModel = require('./createschema.js');
let tabledata =
dynamicModel(collection)

Related

Delete a MongoDB document in Express JS

I'm staggered by how much I'm struggling to delete a document in MongoDB from Express JS. I'm finding the mix of documentation and methods including deleteOne, findByIdAndRemove, some tutorials say you need to declare an ObjectId, and some don't. Madness.
Anyway, below is my code. I have a function to connect to the database:
const withDB = async (operations, res) => {
try {
const client = await MongoClient.connect('mongodb://localhost:27017', { useNewUrlParser: true });
const db = client.db('database-name');
await operations(db);
client.close();
} catch (error) {
res.status(500).json({ message: 'Error connecting to db', error });
}
}
And then the below is my delete command:
app.delete('/api/reports/delete-report/:id', async (req, res) => {
//call withDB function above
withDB(async (db) => {
//delete command
const result = await db.collection('reports').deleteOne( { _id : new MongoClient.ObjectId(req.params.id) } );
//get reports
const reportInfo = await db.collection('reports').find().toArray()
//put returned reports into the result provided
res.status(200).json(reportInfo);
}, res);
});
For my troubles I get the message 'Error connecting to db'. If I make the delete command:
const result = await db.collection('reports').deleteOne( { _id : req.params.id } );
I just get the contents of the database returned, but there's no deletion.
The issue is:
new MongoClient.ObjectId(req.params.id)
You don't want to create another mongoclient. It needs to be
new ObjectId(req.params.id)
and make sure you import that class:
const { MongoClient, ObjectId } = require('mongodb');

model.save() not working using Mongoose and MongoDB Atlas

I am new to using MongoDB, and trying to save some data into MongoDB Atlas using Mongoose. I am possibly doing something blatantly wrong, but I do not understand why it is not working. I get no response from it, no error.
Here is the code:
File 1:
const SavedGuild = require('./models/guild.js');
module.exports = new class {
async get(id) {
return await SavedGuild.findById(id)
|| await new SavedGuild({ _id: id }).save();
}
}
(I have tried SavedGuild({ _id: id }).markModified("guild").save(), same result)
File 2 (./models/guild.js):
const { model } = require('mongoose');
class GeneralModule {
prefix = '/';
blacklistedChannelIds = [];
}
module.exports = model('guild', {
_id: String,
general: { type: Object, default: new GeneralModule() }
});
Mongoose is initiated with this code:
const mongoose = require('mongoose');
try {
mongoose.connect(
`${process.env.mongourl}`,
{ useNewUrlParser: true, useUnifiedTopology: true },
() => console.log("Mongoose is connected")
);
} catch (e) {
console.log("Mongoose could not connect");
}
All help appreciated!

How to create mongodb collections using 'node-mongodb-native' with validators as per defined mongoose schema?

I want to create empty collections with validators that work same when we want to insert or update using mongoose!
In-short, validations at collection-level!
I've tried creating mongodb schema ($jsonSchema) using mongoose-schema-jsonschema, but it throws error Unknown $jsonSchema keyword: x-ref
const mongoose = require('mongoose');
require('mongoose-schema-jsonschema')(mongoose);
const contact = require('./schemas/contact');
contact.jsonSchema('name mobile email message token is_active status status_comment version');
const contact_schema = contact.jsonSchema('', 'country_id state_id suburb_id subject_id created_by modified_by');
let connection;
const get_mongodb_resource = async () => {
try {
console.log('get_mongodb_resource started ');
const options = { useNewUrlParser: true, useCreateIndex: true };
await mongoose.connect(process.env,MONGODB_URI, options);
mongoose.set('debug', true);
console.info('get_mongodb_resource connected');
connection = mongoose.connection;
connection.db.createCollection('contact_schema', { validator: { $jsonSchema: contact_schema } });
return mongoose.connection;
} catch (error) {
console.log('connection to mongodb failed');
console.log(error, error.stack);
return new Error(error);
}
};
How can I do this, either with node-mongodb-native or with mongoose?

Mongoose pagination from server side

I am trying to add server side pagination to a NodeJS, Express and MongoDB API. The API use mongoose to handle the database. I am lost in how to customize the response from the Controller.
Model:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const clientSchema = Schema({
code: {
type: String,
required: [true,'Code no puede estar vacio']
},
name: {
type: String,
required: [true,'Name no puede estar vacio']
}
},{
timestamps: true
});
const Client = module.exports = mongoose.model('clients',clientSchema);
Controller for get all clients:
const mongoose = require("mongoose");
const Client = require('../models/client');
const clientController = {};
clientController.index = (limit, callback) => {
Client.find(callback).limit(limit);
};
module.exports = clientController;
Route to get the clients:
app.get('/api/clients', (req, res) => {
Client.index(limit,(err, client) => {
if (err) {
res.status(500).json({
msg: "Error en aplicacion",
err
});
}
res.status(200).json(client);
});
});
How can I customize the result in the controller to something like this:
[
{
"totalRecords":"99999999999",
"offset":"888888",
"page":"4",
"nextPage":"5"
"result":{...}
}
]
I already have a function to calculate the pagination, But I don't know how to add the information about the pagination in the result of the controller.
Before I was adding the pagination data in the route, But I want to handle the pagination logic in the controller.
Or is better handle the pagination in the route?
Thanks in advance
You can create a method in mongoose model called as paginate :
Add this before declaring mongoose model :
clientSchema.methods.paginate = function(pageNo, callback){
var limit = 10;
var skip = pageNo * (limit - 1);
var totalCount;
//count documents
this.count({}, function(err, count)){
if(err){
totalCount = 0;
}
else{
totalCount = count;
}
}
if(totalCount == 0){
return callback('No Document in Database..', null);
}
//get paginated documents
this.find().skip(skip).limit(limit).exec(function(err, docs){
if(err){
return callback('Error Occured', null);
}
else if(!docs){
return callback('Docs Not Found', null);
}
else{
var result = {
"totalRecords" : totalCount,
"page": pageNo,
"nextPage": pageNo + 1,
"result": docs
};
return callback(null, result);
}
});
});
const Client = module.exports = mongoose.model('clients',clientSchema);
Then in controller change :
app.get('/api/clients', (req, res) => {
//You could put page number in request query ro request params
Client.paginate(req.body.pageNo, function(err, response) {
if (err) {
return res.status(500).json({
message : "Error en aplicacion",
error : err
});
}
return res.status(200).json(response);
});
});

Mongoose update query not working with node.js

First I am making entries in mongodb by:
var device = new Device(inputDetailsJson); //device model instance
device.save(function(err) {
if (err) {
res.send(err);
} else {
res.write('Successful');
res.end();
}
});
This is the device model:
// Dependencies
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
// Schema Definition
var deviceSchema=new Schema ({
"deviceId":{ type : String , unique: true},
"version":{ type : String },
"manufacturer":{ type : String },
"modelname":{ type : String },
});
// Model
module.exports = mongoose.model('de', deviceSchema);
This is the inputDetailsJson:
{
"deviceId":"3236172417",
"version":"5.2.3",
"manufacturer":"abc",
"modelname":"example"
}
These details are getting entered correctly, but when I try to update something, it reflects no changes.
var device=new Device();
device.update({deviceId:"3236172417"},{modelname:"test"}
,function(err) {
if (err) {
return console.error(err);
}
else{
res.write('successful');
res.end();
It displays 'successful' even though no changes are made in the mongodb database.
var Device = require('your device model file');
Device.model.findOneAndUpdate({
deviceId:"3236172417",
},{$set:{modelname:"test}},function(err, user) {
});
For updating the device you don't need to create a new device, using var device=new Device();
you should simply update, same as you try to find a document.
Device.update({deviceId:"3236172417"},{modelname:"test"}
,function(err) {
if (err) {
return console.error(err);
}
else{
res.write('successful');
res.end();

Resources