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

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!

Related

Why can't I get the error VersionError: No matching document found for id

I want to intentionally generate the VersionError: No matching document found for id .... error in mongoose.
Based on what I read in this question here: Mongoose - Version Error: No matching document found for id
it seems like Mongoose will try to protect against duplicate save() because it has some kind of version control.
To try to intentionally generate this error, I wrote this script:
// file: app.js
const dotenv = require('dotenv');
dotenv.config();
const mongoose = require('mongoose');
const opts = {
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true,
useFindAndModify: true,
authSource: 'admin',
};
const schema = mongoose.Schema({
serialNumber: { type: String },
customId: { type: String },
});
const Cms = mongoose.model('Cms', schema);
const run = async () => {
try {
await mongoose.connect(process.env.MONGODB_URL, opts);
const cms1 = await Cms.findOne({});
const cms2 = await Cms.findOne({});
const randomString = new Date().toString();
cms1.serialNumber = `${randomString}AA`;
cms1.customId = `${randomString}AA`;
await cms1.save();
cms2.serialNumber = `${randomString}BB`;
await cms2.save();
} catch (e) {
console.log('err', new Date(), e.toString());
}
/* eslint-disable no-process-exit */
process.exit();
};
run();
I made sure I had exactly 1 record in my cms collection. Then I ran node app.js. I did not get any errors and I see the cms record in my mongo was updated.
I updated my run() to use a setTimeout() like this:
const run = async () => {
try {
await mongoose.connect(process.env.MONGODB_URL, opts);
const cms = await Cms.findOne();
let randomString = new Date().toString();
setTimeout(async () => {
randomString = new Date().toString();
cms.serialNumber = `${randomString}BB`;
// cms.customId = `${randomString}BB`;
await cms.save();
/* eslint-disable no-process-exit */
process.exit();
}, 2000);
cms.serialNumber = `${randomString}AA`;
cms.customId = `${randomString}AA`;
await cms.save();
} catch (e) {
console.log('err', new Date(), e.toString());
}
};
The node app.js ran successfully again and mongoose also saved the record inside the setTimeout.
How do I intentionally generate the VersionError: No matching document found for .... error? What am I missing?

How to use mongoose and nodejs to insert document without having a schema

I'm using nodejs and mongoose in my project, when I'm trying to add a document to mongodb database, Ifound an emty document, I dont know why ?
Method :
const createUser = async (req, res) => {
try {
req = matchedData(req)
const doesUserExists = await userExists(req.email)
if (!doesUserExists) {
res.status(201).json(await createItem(req,User))
}
} catch (error) {
handleError(res, error)
}
}
createItem :
const createItem = (req = {}, model = {}) => {
return new Promise((resolve, reject) => {
console.log(req)
model.create(req, (err, item) => {
if (err) {
reject(buildErrObject(422, err.message))
}
resolve(item)
})
})
}
User Model :
const mongoose = require('mongoose')
const mongoosePaginate = require('mongoose-paginate-v2')
const UserSchema = new mongoose.Schema({})
UserSchema.plugin(mongoosePaginate)
module.exports = mongoose.model('User', UserSchema, 'users')
postman test :
can anyone understand why I'm getting en empty result please ?
this could help -> https://mongoosejs.com/docs/guide.html#strict
im guessing you should have it like
const UserSchema = new mongoose.Schema({..}, { strict: false })

Cannot access mongoose schema attribute

So... I basically search an item in the database, find it, print it fine but I can t access the attributes. When I try to print them they show undefined.
I know that the attribute are in fact undefined because it doesn t break the loop and I do have both attributes in my mongoose schema. I also tried to stringify and parse it to json back and didn t work. (this is all the material I could find)
This is the script:
const name_to_find = 'Copac';
async function myFetch(){
const express = require('express');
const mongoose = require('mongoose');
const Item = require('./models/Item');
const mongoUrl = process.env.MONGO_URL;
const appsc = express();
var connectWithRetry = function() {
return mongoose.connect(mongoUrl, { useNewUrlParser: true, useUnifiedTopology: true }, function(err) {
if (err) {
console.error('Failed to connect to mongo on startup - retrying in 3 sec', err);
setTimeout(connectWithRetry, 3000);
}
});
};
connectWithRetry();
var date1 = new Date();
while(true){
var date2 = new Date();
if(date1.getTime() - date2.getTime() > 100000)
break;
try {
const response = await Item.find({name: name_to_find});
var mergi = JSON.parse(JSON.stringify(response));// doesn t work
//if (response['status'] == 1)
if(response.status == 1){
console.log("200");
break;
}
else {
console.log(JSON.stringify(response));
console.log(response.status);
console.log(mergi.name);
}
}
catch (err) {
console.error(err);
console.log(name_to_find);
}
}
}
myFetch();
this is the schema:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const ItemSchema = new Schema({
status: {
type: Number,
required: true
},
name: {
type: String,
required: true
}
});
module.exports = Item = mongoose.model('item', ItemSchema);
and this is the output:
[{"_id":"60fc235414d05a001a5fa630","status":1,"name":"Copac","__v":0}]
undefined undefined
As u see, it is indeed 1 and should exit the loop but it doesn t.
nothing here helped either link.
Ok so the problem was that mongoose treats the result of .find() function as an array and I should have casted it with results[0] or use .findOne(). I chose the former. The answer was actually in the link provided but u have to scroll a bit for it. Tell me if u want me to delete this

How to get data from mongodb for dynamically created schema model

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)

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?

Resources