Mongoose save : saving failed without error - javascript

I'm building a simple app with mongoose to save some data from an IRC channel.
I have a remote database on a OVH VPS where I can access and log-in without any problems.
However when I try to save some data on it I can't go it with my javascript code.
Here is the data I would like to save :
"use strict"
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
mongoose.Promise = global.Promise;
var UserPointDataSchema = new Schema({
username: String,
value: Number,
channel: String,
timestamp: Number
});
var UserPointDataModel = mongoose.model('UserPointData',UserPointDataSchema);
class UserPointData{
constructor(username,value,channel){
this.username = username;
this.value = value;
this.channel = channel;
this.timestamp =Date.now();
this.mongooseModel = this.toMoogoseModel();
return this;
}
toMoogoseModel(){
return UserPointDataModel.hydrate(this);
}
save(){
this.mongooseModel.save(function (err, product, numAffected) {
if (err){
console.log(err);
}
console.log(err);
console.log(product);
console.log(numAffected);
});
}
}
module.exports = UserPointData;
Here is the output on the console :
null
{ username: 'breci', value: 1, channel: 'breci', timestamp:
1478897691976 }
0
MongoDB version : 3.2.10
Mongoose version : 4.6.6
I checked the logs, no identification problem, no error too.
Someone has an idea why it is not working ?

Solved it by changing the toMongooseModel() method
Here is the new one if someone has the same problem need it :
toMoogoseModel(){
var data = {
username :this.username ,
value: this.value,
channel: this.channel,
timestamp: this.timestamp
}
var res = new UserPointDataModel(data);
return res;
}
If anyone know why the hydrate method didn't work I'm curious to know.

Related

How to get the time a post request was made using Javascript in node.js

I'm making a basic blog application(I'm a newcomer to web development,so I'm building thisfor learning reasons, so nothing advanced), and when someone needs to publish something they head over to a"/compose" route. And when they publish a POST request is made to the server like this,
app.post("/compose",function(req,res){
const postTitle = req.body.postTitle;
const postCategory = req.body.postCategory;
const postBody = req.body.postBody;
const authorName = req.body.authorName;
if (postCategory === "movies"){
MoviePost.findOne({title: postTitle}, function(err, foundPost){
if(!err){
if (!foundPost){
const newPost = new MoviePost({
title: postTitle,
content: postBody,
category: postCategory,
author: authorName
});
newPost.save(function(err){
if(!err){
res.redirect("/");
}
});
} else {
res.send("Post title already exists!Revisit the compose page to publish anything else.")
}
} else {
console.log(err);
}
});
});
and it works fine as of now(I also use Body-Parser. But I also need to know the time the request was made so I can include the written time in the Blog Post. How can I go about achieving it?
If you're using mongoose, you can simply add an extra property to your schema:
const { Schema } = require("mongoose");
const MovieSchema = new Schema({
title: String,
content: String,
category: String,
author: String,
date: { type: Date: default: () => new Date() }
});
This will automatically add the date to the new document when it is saved to the database, so you don't have to do it manually.
I think I figured it out , I did it like this(I also updated the post Schema.),
const postCategory = req.body.postCategory;
const postBody = req.body.postBody;
const authorName = req.body.authorName;
const addedDate = new Date();
const addedTime = addedDate.toString();
if (postCategory === "movies"){
MoviePost.findOne({title: postTitle}, function(err, foundPost){
if(!err){
if (!foundPost){
const newPost = new MoviePost({
title: postTitle,
content: postBody,
category: postCategory,
author: authorName,
time : addedTime
});
newPost.save(function(err){
if(!err){
console.log(addedTime);
res.redirect("/");
}
});
} else {
res.send("Post title already exists!Revisit the compose page to publish anything else.")
}
} else {
console.log(err);
}
});
});

Mongoose: TypeError: Cannot read property 'findOne' of undefined

I am working on billing in node.js and I created a new Model Stripecustomer where I save the stripe customer id and this customer's email. I kinda copied the main code form my other mongoose models and changed it. I had hoped to instantly start using it but when I tried to find a document in this model I got the following error:
⛔️ Error:
TypeError: Cannot read property 'findOne' of undefined
I have looked at it for half an hour and I can't see what I did wrong. Can anyone tell me where I did something wrong?
workspace.controller.js: here is where I try to create a subscription. Stripecustomer is undefined, but I don't get why since I imported it on top
const stripe = require("stripe")("sk_test_dvebbZQPA4Vk8kKZaEuN32sD");
const {
Group, User, Workspace, Stripecustomer
} = require('../models');
const { sendErr } = require('../../utils');
const billing = async (req, res) => {
try {
const email = 'tijl.declerck#outlook.com';
// get the payment plan
const plan = await stripe.plans.retrieve('plan_EK1uRUJLJcDS6e');
// get the stripe customer or create a new one
let customer;
const existingCustomerDoc = await Stripecustomer.findOne({ email: email });
// if we couldn't find an existing customer in our database...
if (!existingCustomerDoc[0]) {
// then we create a new customer
customer = await stripe.customers.create({
email,
source: 'src_18eYalAHEMiOZZp1l9ZTjSU0'
});
} else {
// we retrieve this customer in stripe
customer = await stripe.customers.retrieve(existingCustomerDoc.customer_id);
}
// subscribe the customer to the plan
// You now have a customer subscribed to a plan.
// Behind the scenes, Stripe creates an invoice for every billing cycle.
// The invoice outlines what the customer owes, reflects when they will be or were charged, and tracks the payment status.
// You can even add additional items to an invoice to factor in one-off charges like setup fees.
const subscription = await stripe.subscriptions.create({
customer: customer.id,
items: [{ plan: plan.id }]
});
res.status(200).json({
message: 'payment complete',
obj: subscription
});
} catch (err) {
return sendErr(res, err);
}
};
stripecustomer.model.js
const mongoose = require('mongoose');
const { Schema } = mongoose;
const stripeCustomerSchema = new Schema({
email: {
type: String,
required: true
},
customer_id: {
type: String,
required: true
}
});
const Stripecustomer = mongoose.model('Stripecustomer', stripeCustomerSchema);
module.exports = Stripecustomer;
The error is probably coming from ur models index.js file, can u share ur models/index.js file to make this more clear, because findOne is a mongoose function, if u get undefined it means Stripecustome is not an instance of a mongoose model

Mongoose unable to get data from MongoDB database

I have a model (AccountModel.js) as below and the controller for it. i tried to change one document using postman but i am getting an empty array from the database event though the data is present.
let mongoose = require('mongoose')
let Schema = mongoose.Schema
var ObjectId = Schema.ObjectId
let mySchema = mongoose.Schema({
account_id:ObjectId,
account_key:String,
message:String,
created_at:Date,
updated_at:Date
})
let MySchema = module.exports =
mongoose.model('account',mySchema);
module.exports.get = function(callback,limit){
MySchema.find(callback).limit(limit)
}
and AccountController as below to manage account db. i have consoled the query and the output from the database.
var mongoose = require('mongoose')
var Account = require('../models/AccountModel')
var ObjectId = mongoose.Types.ObjectId;
exports.setMessage = function(req,res){
query = {account_id:new ObjectId(req.body.acnt_id)}
console.log(query,"...")
Account.find(query,function(err,account_data){
if(err){
res.send(err)
}
else{
try{
console.log(account_data,'setWelcomeMessage')
account_data.message =
req.body.welcomeMessage
account_data.updated_at = new Date()
account_data.save((err,data)=>{
if(err){
console.log(err)
res.send(err)
}
res.send({"Status":"Success"})
})
res.send({"Status":"Success"})
}
catch(e){
//console.log(e)
res.send({"Status":"Failed"})
}
}
})
}
below is the database
> db.account.find().pretty()
{
"_id" : ObjectId("5c18fea5c5a6a4ebf7999c0b"),
"account_id" : ObjectId("5c18fbefc5a6a4ebf7999c08"),
"account_key" : "UDS1500",
"message" : "testing message",
"created_at" : ISODate("2018-12-18T14:05:25.637Z"),
"updated_at" : ISODate("2018-12-18T14:05:25.637Z")
}
{
"_id" : ObjectId("5c18feffc5a6a4ebf7999c0c"),
"account_id" : ObjectId("5c18fbaac5a6a4ebf7999c07"),
"account_key" : "UDS1299",
"message" : "testing message2",
"created_at" : ISODate("2018-12-18T14:06:55.968Z"),
"updated_at" : ISODate("2018-12-18T14:06:55.968Z")
}
after calling from POSTMAN i am getting an empty array
Below is the request format
{
"acnt_id":"5c18fbaac5a6a4ebf7999c07",
"welcomeMessage":"test message 3!!"
}
console is as below
{ account_id: 5c18fbaac5a6a4ebf7999c07 } '...'
[] 'setWelcomeMessage'
what might be the problem in getting empty data? i have wasted a lot of time on this.
The culprit is this line
query = {account_id:new ObjectId(req.body.acnt_id)}
where the statement new ObjectId(req.body.acnt_id) creates a new id (regardless of what you pass in the constructor) thus your query fails as there won't be any match in the db. You don't necessarily need to cast the acnt_id string to ObjectId as Mongoose does this for you under the hood, but if need be use
query = {account_id:mongoose.Types.ObjectId(req.body.acnt_id)}
otherwise
query = {account_id:req.body.acnt_id}
will suffice.
A better way to do the update would be to use the findOneAndUpdate method which does an atomic update of your model and mostly used when you want to update a single document in the db and return it to your application, so you can refactor your controller method to:
exports.setMessage = (req, res) => {
const query = { 'account_id': req.body.acnt_id };
const update = {
'$set': {
'message': req.body.welcomeMessage,
'updated_at': new Date(),
}
};
const options = { 'new': true };
Account.findOneAndUpdate(query, update, options, (err, account_data) => {
if (err){
res.send(err)
}
else {
console.log(account_data); // logs the updated account document
res.send({"Status":"Success"})
}
});
}
Also, you can set timestamps in your schema where mongoose assigns createdAt and updatedAt fields to your schema and the type assigned is Date i.e.
let mySchema = mongoose.Schema({
account_id: ObjectId,
account_key: String,
message: String,
}, { timestamps: { createdAt: 'created_at', updatedAt: 'updated_at' } });
.find() returns an array, not a single element. Therefore i'd recommend using the .findOne() method instead.
Thank you for you response. I found answer for my problem.
The reason is that the mongoose has created a model with the plural name. Which means, here i have named the model "account". But here in database it will create/connect to a collection with the name "accounts". I dont know the reason for mongoose not creating/connecting to a collection named "accounts". Since there is no collection named with "accounts" it is always giving me the empty result.
At last, i have changed the collection name to "accounts". Now it working fine.
Please comment the reason, mongoose creating/connecting to plural name of the given model.
//getting from postman .... give the account id in postman
query = {account_id:req.body.acnt_id};
//there is match in DB--- getting the data
Account.find(query,function(err,account_data){
if(err){
res.send(err)
}
u wana update
else{
Accoun.update({account_id:req.body.acnt_id},req.body
};
//on body what you enter in postman that will update and store on DB
IN MY KNOWLEDGE
// just example
Model.update
Updates all documents matching conditions using the update clause. All update values are casted to their appropriate types before being sent.
var conditions = { name: 'bourne' }
, update = { $inc: { visits: 1 }}
, options = { multi: true };
Model.update(conditions, update, options, callback);
function callback (err, numAffected) {
// numAffected is the number of updated documents
})

Assign property value doesn't work in Mongoose

My query is:
db.Room.find({}, function (err, rooms) {
if (!err) {
async.each(rooms, function (room, done) {
db.User.find({}, function (err, users) {
if (err) {
done(err)
} else {
room.users = users
room._name = room.name
done()
}
})
}, function (err) {
if (!err) {
socket.emit('read:rooms', rooms)
}
})
}
})
and schemas are:
room:
var mongoose = require('mongoose')
var Schema = mongoose.Schema,
ObjectId = Schema.ObjectId;
var Room = new Schema({
name: String
});
module.exports = Room
user:
var mongoose = require('mongoose')
var Schema = mongoose.Schema,
ObjectId = Schema.ObjectId;
var User = new Schema({
email: String
});
module.exports = User
but in front-end:
socket.on('read:rooms', function (rooms) {
$scope.rooms = rooms
})
but rooms has no users property, help me, please
It's because the Rooms schema doesn't have a users property.
So, there are a few ways to fix it. Since it looks like though you want the users property to be something that really isn't part of the schema, and is a client-side join rather than work that is done on the database (which is a good!), I'd suggest you convert the data to be just plain old JavaScript objects when you send it over the socket (this would have happened anyway, you're just doing it a bit earlier).
So, when the find returns, it is actually returning a fully-realized MongooseJS model object. While you can set dynamic properties on the object instance, they aren't part of the "data" of the model, so that when it is serialized later to the client, only the properties that are documented will be available.
So, here is an example of what I'd suggest:
db.Room.find({}, function (err, rooms) {
if (!err) {
var oRooms = [];
async.each(rooms, function (room, done) {
/* etc. your code */
} else {
var oRoom = room.toObject();
oRoom.users = users
oRoom._name = room.name
oRooms.push(oRoom);
done()
}
This technique would use the toObject functionality of a Model to return a JavaScript object (not a Mongoose model). That way, you can do what you'd like to the object, including adding new properties dynamically.
Later, of course, make sure you send the new array of rooms to the client:
if (!err) {
socket.emit('read:rooms', oRooms)
}

what's wrong with this model

I need to develop a module for getting data from mongodb, I already have other models working in my application, but this one does not, this is my schemas:
var mongoose = require('mongoose');
var ProvinciaSchema = new mongoose.Schema({
"nome":String,
"tc_provincia_id":Number,
"id" : Number,
"codice_regione" : Number,
"codice" : Number,
"sigla" : Number
},{collection:'province'})
module.exports = ProvinciaSchema;
this is my model:
var mongoose = require('mongoose');
var ProvinciaSchema = require('../schemas/provincia');
var Provincia = mongoose.model('provincia', ProvinciaSchema);
module.exports = Provincia;
This is how I use the model:
var Provincia = require('../../models/provincia');
Provincia.find({},next( err, province){
if (err){console.log('errorre whoosh '+err);
return next(err,province)
}
if (!province){console.log('trovato nulla')}
console.log('callback tc_istat_id')
return next(err,province)
})
where
next =function(err,prov){
t.equivalent(out,expect)
t.end()
when I launch the test if the condition argument is correct, the execution stuck at Provincia.find and the callback function it is not executed, if I put a wrong condition the section of the code of if(err) is executed, I think there is a problem with my schemas abnd models, but I do not understand what.
function myFunction(callback) {
Provincia.find({},next( err, province){
if (err) {
console.log('errorre whoosh '+err);
return next(err,province)
}
if (!province){
console.log('trovato nulla');
return false;
}
console.log('callback tc_istat_id')
callback(err,province)
})
}
myFunction(function(err,prov){
t.equivalent(out,expect)
t.end()
});
I had no way of testing this but it is how I would set up my callback function. Let me know what you log, and what errors your get if this does not work

Categories