How to add new object by id to mongoDB collection? - node.js

I have a collection called Users which stores user's messages & info. I want to add new objects to existing collection by it's id.
I receive an error 'TypeError: user.insert is not a function' - i guess i missed something....
Here is the method from the controller :
UserDataController.prototype.sendMsg = function (userID, messages_data, cb) {
if (userID) {
user.findOne({_id: userID},function(err, result){ //Object id=59e5e542a5ba05056c57d847
// insert to the collection with the object id
user.insert({_id: userID} ,messages_data,function(err, result){
if(err) return cb(err);
return cb(null, result);
});
});
}
};
Here is the result i wish to get :
"sentmessages" : [{
"message_body" : "whatsup", // new object
"message_subject" : "whatsup",
"message_date" : "20/01/2017"
},
{
"message_body" : "whatsup", // new object
"message_subject" : "whatsup",
"message_date" : "20/01/2017"
}]
The schema looks like that :
var sentmessages = new schema({
message_date: String,
message_subject : String,
message_body : String,
});
var UserSchema = new schema({
firstname: String,
lastname: String,
email: String,
sentmessages :[sentmessages] // here is were i want to add new objects
});

Got it... needed to use $push
UserDataController.prototype.sendMsg = function (userID, messages_data, cb)
{
if (userID) {
var message_fixesd_data = messages_data.sent_messages[0];
user.update({_id: userID},
{ $push: { sent_messages: {
message_body : message_fixesd_data.message_body,
message_subject: message_fixesd_data.message_subject,
message_date : message_fixesd_data.message_date
}
}
}, function (err, result) {
if(err)
{
return cb(err);
}
else
{
return cb(true, 'File was save successfully', result);
}
});
}
};

Related

updating nested documents in mongoDB(node.js)

i am trying to update a value in the object of my embedded schema(comments schema) whose value i had previously stored 0 by default. i have tried all the ways to update but none of the stackoverflow answer worked.
my code is
var checkedBox = req.body.checkbox;
User.updateOne({_id: foundUser._id},{$set :{comments:{_id :checkedBox,cpermission:1,}}},function(err,updatec){
if(err){
console.log(err);
}
else{
console.log("successfull");
console.log(updatec);
}
});
i had comment schema nested in user schema,here foundUser._id is the particular users id,and checkedBox id is the embedded objects particular id. previously my cpermission was 0,set by default,but now i want to update it to 1. although this is updating my schema,but deleting the previous images and comments in the schema aswell.
where am i going wrong?
here is my schema
const commentSchema = new mongoose.Schema({
comment: String,
imagename: String,
cpermission:{type:Number,default:0},
});
const Comment = new mongoose.model("Comment", commentSchema);
const userSchema = new mongoose.Schema({
firstname: String,
lastname: String,
email: String,
password: String,
comments: [commentSchema],
upermission:{type:Number,default:0},
});
userSchema.plugin(passportLocalMongoose);
const User = new mongoose.model("User", userSchema);
First, you need to convert checkbox in the array, as it will be a string if you select a single element
Then wrap it with mongoose.Types.ObjectId as a precaution
Then you can use arrayFilters to update multiple matching array elements
var checkedBox = req.body.checkbox;
if (!Array.isArray(checkedBox)) {
checkedBox = [checkedBox]
}
checkedBox = checkedBox.map(id => mongoose.Types.ObjectId(id))
User.updateOne(
{ _id: foundUser._id }, // filter part
{ $set: { 'comments.$[comment].cpermission': 1 } }, // update part
{ arrayFilters: [{ 'comment._id': {$in: checkedBox }}] }, // options part
function (err, updatec) {
if (err) {
console.log(err);
}
else {
console.log("successfull");
console.log(updatec);
}
});
your comment is the array of documents. if you want to update an element of an array must be select it. for that must be added another condition to the first section of updateOne then in seconde section use $ for update selected element of the array.
User.updateOne(
{_id: foundUser._id, 'comments._id': checkedBox},
{
$set: {'comments.$.cpermission': 1}
}
, function (err, updatec) {
if (err) {
console.log(err)
}
else {
console.log('successfull')
console.log(updatec)
}
})
for more information, you can read this document form MongoDB official website.
Array Update Operators
var checkedBox = req.body.checkbox;
User.updateOne(
{ _id: foundUser._id, "comment._id": checkedBox },
{ $set: { "comment.$.cpermission": 1 } },
function (err, update) {
if (err) {
console.log(err);
} else {
console.log("successfull");
console.log(update);
}
}
);

How to link a collection with user?

I am working on MEAN application(Angular2+). I want to maintain a seprate data for each user. As of now the data are like anyone can view any of the details but i want like, If i login and enter details, only I can view those details. Basically I want to link user collection with other collection. Since I am new to Mongo, I have no idea about this.
user.ts
import * as mongoose from 'mongoose'
const userSchema = new mongoose.Schema({
username: String,
email: { type: String, unique: true, lowercase: true, trim: true },
password: String,
role: String
});
cat.ts
import * as mongoose from 'mongoose';
const catSchema = new mongoose.Schema({
name : String,
height: String,
weight: String,
});
I have no idea what is this
base.ts
abstract class BaseCtrl {
abstract model: any;
// Get all
getAll = (req, res) => {
this.model.find({}, (err, docs) => {
if (err) { return console.error(err); }
res.json(docs);
});
}
// Count all
count = (req, res) => {
this.model.count((err, count) => {
if (err) { return console.error(err); }
res.json(count);
});
}
// Insert
insert = (req, res) => {
const obj = new this.model(req.body);
obj.save((err, item) => {
// 11000 is the code for duplicate key error
if (err && err.code === 11000) {
res.sendStatus(400);
}
if (err) {
return console.error(err);
}
res.status(200).json(item);
});
}
// Get by id
get = (req, res) => {
this.model.findOne({ _id: 'req.params.id '}, (err, obj) => {
if (err) { return console.error(err); }
res.json(obj);
});
}
// Update by id
update = (req, res) => {
this.model.findOneAndUpdate({ _id: req.params.id }, req.body, (err) => {
if (err) { return console.error(err); }
res.sendStatus(200);
});
}
// Delete by id
delete = (req, res) => {
this.model.findOneAndRemove({ _id: req.params.id }, (err) => {
if (err) { return console.error(err); }
res.sendStatus(200);
});
}
}
export default BaseCtrl;
Reference project : https://github.com/DavideViolante/Angular-Full-Stack
You need to add user_id field to catSchema. The user_id will be the reference for the user who add/save that cat.
cat.ts
import * as mongoose from 'mongoose';
const catSchema = new mongoose.Schema({
name : String,
height: String,
weight: String,
user_id: String, // Or may be ObjectId
});
And you need to query the user from users collection to retrieve the data everytime.
Or you can use DBRef of mongodb. To implement this in mongoose you can follow this link.
Basically your cat model will be
cat.ts
import * as mongoose from 'mongoose';
const catSchema = new mongoose.Schema({
name : String,
height: String,
weight: String,
user: { type: mongoose.Schema.ObjectId, ref: 'User' }
});
To insert the cat, get the userid from login details/sessions and add to collection.
For you, you need to add the 'user' field to req.body as in base controller you are creating model from req.body.
If you don't want to add to req.body, you can override the insert method for cat controller and manually create the cat model with userid.
controller/cat.ts
import Cat from '../models/cat';
import BaseCtrl from './base';
export default class CatCtrl extends BaseCtrl {
model = Cat;
insert = (req, res) => {
const data = {
title: req.body.title,
height: req.body.height,
weight: req.body.weight,
user: getUser() // Get the logged in userid
};
const obj = new this.model(data);
obj.save((err, item) => {
if (err && err.code === 11000) {
res.sendStatus(400);
}
if (err) {
return console.error(err);
}
res.status(200).json(item);
})
}
}
Just like above, you can modify and filter all your documents according to user.
Edit:
To make it simple, send the current logged in user in the form itself. cats.component.ts
addCat() {
this.addCatForm.value.userid = this.authService.currentUser._id; // You might need to use callback here
... // All other code
}
Revert the cat controller to as it was before.

MongoDB - Handle error event

I have a custom validation when I upload an image to mongoDb. The original name should be unique. If it passes the validation, the code runs properly. But if it fails, it produces error. It says that custom validators that take 2 arguments) are deprecated in mongoose >= 4.9.0. Is there another way to validate the uniqueness of the originalname? Or a way to catch the error? Please help.
router.post('/upload',function(req,res){
Item.schema.path('originalname').validate(function(value, done) {
Item.findOne({originalname: value}, function(err, name) {
if (err) return done(false);
if (name) return done(false);
done(true);
});
});
upload(req,res,function(err, file) {
if(err){
throw err;
}
else{
var path = req.file.path;
var originalname = req.file.originalname;
var username = req.body.username;
var newItem = new Item({
username: username,
path: path,
originalname: originalname
});
Item.createItem(newItem, function(err, item){
if(err) throw err;
console.log(item);
});
console.error('saved img to mongo');
req.flash('success_msg', 'File uploaded');
res.redirect('/users/welcome');
}
});
});
model
var ItemSchema = mongoose.Schema({
username: {
type: String,
index: true
},
path: {
type: String
},
originalname: {
type: String
}
});
var Item = module.exports = mongoose.model('Item',ItemSchema);
module.exports.createItem = function(newItem, callback){
newItem.save(callback);
}
you can provide uniqueness to that field like :-
var ItemSchema = mongoose.Schema({
username: {
type: String,
index: true
},
path: {
type: String
},
originalname: {
type: String,
unique:true // this string will be unique all over the database
}
});
var Item = module.exports = mongoose.model('Item',ItemSchema);
module.exports.createItem = function(newItem, callback){
newItem.save(callback);
}
To validate uniqueness before saving to db, you can try to findOne with tour filename:
router.post('/upload',function(req,res){
Item.findOne({originalname: req.file.originalname}, function(err, name) {
if (err) return done(false); // errors
if (name) return done(false); // check for existence of item here
done(true);
});
});
If findOne function did not respond with any data, it means that, there is no document in collection with the same original name, and you can proceed with adding document to collection

Mongoose populate issue - array object

My schema is as below
Sectionschema
var SectionSchema = new Schema({
name: String,
documents : {
type : [{
type: Schema.ObjectId,
ref: 'Document'
}]
}
}
}
DocumentSchema
var DocumentSchema = new Schema({
name: String,
extension: String,
access: String, //private,public
folderName : String,
bucketName : String,
desc: String
});
Api.js
exports.section = function(req, res, next, id) {
var fieldSelection = {
_id: 1,
name: 1,
documents : 1
};
var populateArray = [];
populateArray.push('documents');
Section.findOne({
_id: id
}, fieldSelection)
.populate(populateArray)
.exec(function(err, section) {
if (err) return next(err);
if (!section) return next(new Error('Failed to load Section ' + id));
// Found the section!! Set it in request context.
req.section = section;
next();
});
}
If I go this way, I have
the 'documents' object is []. However if I remove, "populateArray.push('documents');" then I get documents:['5adfsadf525sdfsdfsdfssdfsd'] -- some object Id (atleast)
Please let me know the way I need to populate.
Thanks.
Change your query to
Section.findOne({
_id: id
}, fieldSelection)
.populate('documents.type')
.exec(function(err, section) {
if (err) return next(err);
if (!section) return next(new Error('Failed to load Section ' + id));
// Found the section!! Set it in request context.
req.section = section;
next();
});
and this works. You need to give the path to populate.
If you just want "documents" in your schema pointing to Array of ObjectID which you will populate later. then you can use this.
var SectionSchema = new Schema({
name: String,
documents : [{
type: Schema.ObjectId,
ref: 'Document'
}]
});
And use the following to populate it
Section.findOne({
_id: id
}, fieldSelection)
.populate('documents')
.exec(function(err, section) {
if (err) return next(err);
if (!section) return next(new Error('Failed to load Section ' + id));
// Found the section!! Set it in request context.
req.section = section;
next();
});

How do I insert an element into an existing document?

I have an existing document that contains a nested array of elements (I'm not exactly sure of the terminology here). I have no problem creating the document. The problem arises when I need to insert a new element into the existing document. The code below may clarify what I'm trying to do:
Controller:
var Post = require('./models/post');
app.post('/post/:id/comment', function(req, res) {
var updateData = {
comments.comment: req.body.comment
comments.name: req.body.name,
};
Post.update({_id: req.params.id},updateData, function(err,affected) {
console.log('affected rows %d', affected);
});
});
Model:
var mongoose = require('mongoose');
var postSchema = mongoose.Schema({
post : String,
name : String,
created : {
type: Date,
default: Date.now
},
comments : [{
comment : String,
name : String,
created : {
type: Date,
default: Date.now
}
}]
});
module.exports = mongoose.model('Posts', postSchema);
So, each post can contain multiple comments. I'm just not sure how to insert a new comment into an existing post.
Since comments is declared as array, try to use
Post.update({_id:yourid}, { $push : { comments: { comment: '', name: '' } } }, ...
You can convert the object returned from mongodb in to an js object, and push new comment into the comments array. See the following:
var postSchema = require('./postSchema'); // your postSchema model file
postSchema.findOne({name: 'name-of-the-post'}, function (err, doc) { //find the post base on post name or whatever criteria
if (err)
console.log(err);
else {
if (!doc) { //if not found, create new post and insert into db
var obj = new postSchema({
post: '...'
name: '...'
...
});
obj.save(function (err) {
if (err)
console.log(err);
});
} else {
// if found, convert the post into an object, delete the _id field, and add new comment to this post
var obj = doc.toObject();
delete obj._id;
obj.comments.push(req.body.comment); // push new comment to comments array
postSchema.update(
{
'_id': doc._id
}, obj, {upsert: true}, function (err) { // upsert: true
if (err)
console.log(err);
});
}
console.log('Done');
}
});

Resources