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.
Related
The below controller deletes a single log perfectly well; however, I cannot for the life of me delete its reference in the Journey model.
Image of the Journey object, one that contains an array of logs
I would greatly appreciate it if someone would be able to shed some light on where i am going wrong.
Journey Model
const mongoose = require("mongoose");
const journey = mongoose.Schema({
title: {
type: String,
},
logs: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'LogEntry'
}]
},
{
timestamps: true,
})
const Journey = mongoose.model("Journey", journey);
module.exports = {Journey};
Logs Model
const mongoose = require("mongoose");
const logEntry = mongoose.Schema({
logTitle: {
type: String
},
journey: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Journey'
}],
},
{
timestamps: true,
})
const LogEntry = mongoose.model("LogEntry", logEntry);
module.exports = {LogEntry};
Controller - delete functionality
const {Journey} = require("../models/Journey");
const {LogEntry} = require("../models/Logs");
exports.log_delete_get = (req, res) => {
LogEntry.findByIdAndDelete(req.query.id).populate('journey')
.then(() => {
res.redirect("/log/index")
})
.catch(error => {
console.log(error)
})
}
EJS View - Initiates delete
<td> Delete </td>
I have tried:
I have tried to use the following, but I am not sure how to correctly implement it:
{$pull: { logs: req.query.id}})
I have tried using a for loop to iterate through the logs array and pop the specific ids but to no avail.
I am aiming to:
When I delete a log, the reference to that log is also removed from the Journey Object.
Fix
I found a solution that works, this will delete a specific Journey and remove all logs associated with that Journey.
exports.journey_delete_get = function(req, res, next){
Journey.findById(req.query.id, function(err, journey) {
if (err) {
return next(err);
}
if (!journey) {
return next(new Error('Failed to load journey ' + req.query.id));
}
journey.remove(function(err) {
if (err) {
return next(err);
}
LogEntry.find({ journey: journey._id }, function(err, logs) {
if (err) {
return next(err);
}
if (!logs) {
return next(new Error('Failed to load logs ' + journey._id));
}
logs.forEach(function(log) {
log.remove(function(err) {
if (err) {
return next(err);
}
});
});
res.redirect("/journey/index")
});
});
});
};
I have this schema for my project but it is not pushing the data in mongo db
let bracketModel = mongoose.Schema(
{
tournamentName: String,
gameType: String,
players: Number,
description: String,
teams: [String],
},
{
collection: "bracketsample",
}
);
here is my function
module.exports.addprocesspage = (req, res, next) => {
let newbracket = Bracket({
tournamentName: req.body.tournamentName,
gameType: req.body.gameType,
players: req.body.players,
description: req.body.description,
$addToset:{teams:[req.body.teams]},
});
Bracket.create(newbracket, (err, Bracket) => {
if (err) {
console.log(err);
res.end(err);
} else {
//refresh the bracket-list
res.redirect("/bracket-list");
console.log();
}
});
};
tried declaring cons varialble=req.body.teams but still not working.
You are missing the "new" syntax before "Bracket". Also you use the create method with the already created "Bracket", i would use save instead. Try this:
let newBracket = new Bracket({
tournamentName: req.body.tournamentName,
gameType: req.body.gameType,
players: req.body.players,
description: req.body.description,
$addToset:{teams:[req.body.teams]},
});
newBracket.save().then(() => {
res.redirect("/bracket-list");
}).catch((err) => {
console.log(err);
res.end(err);
});
Working on a personal project, one of the functions of the project is to update the user status on what event they are participating.
i wanted to submit a value using a button
<form action="/users/fooddrivebanner" method="POST"><button name="fooddrive" type="submit" value="fooddrive" id="fooddrive">Participate</button></form>
then pass the value to my route and save it inside my database
router.post('/fooddrivebanner', (req,res)=>{
const { fooddrive } = req.body;
const _id = ObjectId(req.session.passport.user._id);
User.findOne({ _id: _id }).then((user)=>{
if (!user) {
req.flash("error_msg", "user not found");
res.redirect("/fooddrivebanner");
}
if (typeof eventparticpating !== "undefined") {
user.eventparticpating = 'fooddrive';
}
user.save(function (err, resolve) {
if(err)
console.log('db error', err)
// saved!
});
})
.catch((err) => console.log(err));
Here is the User model
const mongoose = require('mongoose');
const UserSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true
},
password: {
type: String,
required: true
},
date: {
type: Date,
default: Date.now
},
eventparticpating: {
type: String,
default: 'None At The Moment'
}
});
const User = mongoose.model('User', UserSchema);
module.exports = User;
It showed a console error
TypeError: Cannot set property 'eventparticpating' of null
UPDATE
Edit 1:
I followed Mr Gambino instructions, error Gone yet cannot update the database, how would i be able to adjust and find my user?
Instead of saving within the findOne function,you can do this:
router.post('/fooddrivebanner', async (req,res) => {
const { fooddrive } = req.body;
const _id = ObjectId(req.session.passport.user._id);
await User.findOne({ _id: _id }, (error, user) => {
if (error) {
req.flash("error_msg", "user not found");
res.redirect("/fooddrivebanner");
}
}).updateOne({ eventparticpating: "foodrive" });
});
I hope that answers your question
This is my schema:
const productSchema = new mongoose.Schema({
name: String,
imageUrl: String,
category: String,
price: Number,
description: String,
featured: {
default: false
},
rating: [
{
userName: String,
score: Number,
comment: String
}
]
});
And this is how I was trying to push data into my database.
app.route("/review").post(function(req, res) {
const score = req.body.score;
const comment = req.body.comment;
if (req.isAuthenticated()) {
const review = {
$push: {
rating: {
userName: req.user.fName,
score: score,
comment: comment
}
}
};
console.log(review, req.body.productName);
Product.updateOne({ name: req.body.productName }, review, function(
err,
done
) {
if (err) {
console.log(err);
} else {
res.redirect("/products");
}
});
} else {
res.redirect("/login");
}
});
In the official documentation, it says that this is the way to push data in the MongoDB array. But still having no luck.
Help me to push reviews in the rating array field.
Thank You.
for my answer im using mongoose function findOneAndUpdate you can use updateOne instead , The writing to the database will be in a async function in order to not block the node process (will be alot faster).
Puting all the code in a try-catch block will allow you to control any errors if accrued.
You can read more about mongoose driver function and findOneAndUpdate here:
https://docs.mongodb.com/manual/reference/method/db.collection.findOneAndUpdate/
more about async function:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
app.route('/review').post(async function(req, res) {
//destructuring values from body-parser
const { score, comment, productName } = req.body;
if (req.isAuthenticated()) {
//creating the rating obj
const rating = {
userName: req.user.fName,
score: score,
comment: comment
};
console.log(review, productName);
//setting it all in a try-catch block
try {
const product = await Product.findOneAndUpdate(
{name: productName},
{ $set: { rating: rating } },
{ new: true }
).then(err => {
if (err) throw err;
return res.redirect('/products');
});
res.redirect('/login');
} catch (error) {
console.log(error);
}
}
});
Hopefully this makes sense, good luck!
Given yon schema, how do I save userId to createdBy and updatedBy?
This seems like it should be an easy use case. How do I do it?
I'm not sure how to get userId from req.user.id to the model before being written.
// graph.model.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var schema = new Schema({
title: String,
createdAt: Date,
createdBy: String,
updatedAt: Date,
updatedBy: String,
});
// This could be anything
schema.pre('save', function (next) {
- if (!this.createdAt) {
this.createdAt = this.updatedAt = new Date;
this.createdBy = this.updatedBy = userId;
} else if (this.isModified()) {
this.updatedAt = new Date;
this.updatedBy = userId;
}
next();
});
Here's the controller code if you're interested:
var Graph = require('./graph.model');
// Creates a new Graph in the DB.
exports.create = function(req, res) {
Graph.create(req.body, function(err, thing) {
if(err) { return handleError(res, err); }
return res.status(201).json(thing);
});
};
// Updates an existing thing in the DB.
exports.update = function(req, res) {
if(req.body._id) { delete req.body._id; }
Graph.findById(req.params.id, function (err, thing) {
if (err) { return handleError(res, err); }
if(!thing) { return res.send(404); }
var updated = _.merge(thing, req.body);
updated.save(function (err) {
if (err) { return handleError(res, err); }
return res.json(thing);
});
});
};
The following is just another way of saving userId.
Sample model with createdBy, updatedBy, createdAt, updatedAt fields:
import mongoose from 'mongoose';
const SupplierSchema = new mongoose.Schema(
{
name: {
type: String,
},
createdBy: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
},
updatedBy: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
},
},
{
timestamps: {
createdAt: true,
updatedAt: true,
},
},
);
export default mongoose.model('Supplier', SupplierSchema);
Note that in mongoose starting from version ^4.13.17 you can simply specify timestamps createdAt, updatedAt directly in the schema.
https://mongoosejs.com/docs/4.x/docs/guide.html#timestamps
Then in supplier controller assign req.user._id to the fields createdBy, updatedBy:
import mongoose from 'mongoose';
import { Supplier } from '../models';
exports.create = async (req, res) => {
const supplierToCreate = new Supplier({
_id: new mongoose.Types.ObjectId(),
name: req.body.name,
createdBy: req.user._id,
updatedBy: req.user._id,
});
return supplierToCreate
.save()
.then(() =>
res.status(201).json({
message: 'New supplier is created successfully.',
}),
)
.catch(errSaving => res.status(500).json({ error: errSaving }));
};
You can't access req object inside of mongoose hook.
I think, you should define virtual field with a smart setter instead:
schema.virtual('modifiedBy').set(function (userId) {
if (this.isNew()) {
this.createdAt = this.updatedAt = new Date;
this.createdBy = this.updatedBy = userId;
} else {
this.updatedAt = new Date;
this.updatedBy = userId;
}
});
Now all you have to do is to set modifiedBy field with correct userId value in your controller:
var updated = _.merge(thing, req.body, {
modifiedBy: req.user.id
});