Mongoose assign a collection to another - javascript

I am trying to add a post to a user collection after the user was created with empty posts. I have tried with populate with no success .. any help is much appreciated.
// Post Model
const mongoose = require('mongoose');
const { Schema } = mongoose;
const UserModel = require('./user-model');
let PostSchema = new Schema({
author: {
ref: 'users',
type: Schema.Types.ObjectId
},
content: String,
description: String,
date: {
default: new Date(),
type: Date
},
title: String,
updatedAt: {
default: new Date(),
type: Date
}
});
let PostModel = mongoose.model('posts', PostSchema);
module.exports = PostModel;
// User Model
const mongoose = require('mongoose');
const { Schema } = mongoose;
const PostModel = require('./post-model');
let UserSchema = new Schema({
name: {
type: String
},
email: {
lowercase: true,
type: String,
trim: true,
unique: true
},
password: {
type: String,
},
postList: [{
ref: 'posts',
type: Schema.Types.ObjectId
}],
});
const UserModel = mongoose.model('users', UserSchema);
module.exports = UserModel;
// save post controller
exports.savePost = (request, response, next) => {
let { author, description, title } = request.body;
let post = new PostModel({ author, description, title }).save();
UserModel.findById(author)
.then((user) => {
user.postList.push(post);
// Still Fails
// How can i assign the post to the user ?
});
}
Is there any way of doing this other then push or populate ?

To solve this problem I prefer to use $push of mongo
UserModel.findOneAndUpdate({
_id: author.id,
{
$push: {
postList: post
}
}
});

You need to follow this process to save successfully
Save post if success then
Update user to push postId in postlist
can try this one
exports.savePost = (request, response, next) => {
let post = new PostModel(request.body)
post.save(function(err, data) {
if(err) {
//return error
}
// check by console your author is present or not
// let author in your req.body
let author = req.body.author
UserModel.findOneAndUpdate({_id: author},{$push: {postList: post._id}},{new:true} function(error, user) {
if(error) {
// return error
}
console.log(user)
// return success
})
});
}

exports.savePost = (request, response, next) => {
let { user, description, title } = request.body;
let post = new PostModel({ user, description, title });
post.save()
.catch((error) => {
if (error)
throw new Error(error);
})
.then((post) => {
UserModel.findOneAndUpdate({ _id: user }, {$push: { postList: post._id } })
.populate('postList')
.catch((error) => {
if (error)
throw new Error(error);
})
.then((user) => {
user.postList.forEach((item, postion) => {
console.log(`${item} -at ${postion} \n`);
});
});
});
}
This is what i did and it worked after all. I don't know if this is the correct solution but this is working.

Related

Mongoose Database populate issue

This is the code
app.get("/cart", checkAuthentication, function (req, res) {
Orders.find({ user: req.user._id })
.populate('user')
.populate('order')
.exec((err, orders) => {
console.log(orders);
if (err) {
console.log("ERROR /cart :\n" + err);
res.redirect("/");
} else {
const OrderList = [];
orders.forEach((order) => {
const obj = {
order: order.order,
id: order._id
}
OrderList.push(obj);
});
var sum=0
OrderList.forEach(function(item){
sum += item.order.price
});
req.session.sum = sum;
req.session.orders = OrderList;
res.render("cart", { itemList: OrderList, login: true, name: req.user.name });
// res.render("cart", { itemList: OrderList, login: false, name: "abc" });
}
});
});
This is order model =>
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const orderSchema = new Schema({
user: { type: Schema.Types.ObjectId, ref: "User" },
order: { type: Schema.Types.ObjectId, ref: "SellingItem" },
date: { type: Date, default: Date.now }
});
module.exports = mongoose.model("Orders", orderSchema);
THIS IS THE ERROR
ERROR(null)
This is the github link for my repo - https://github.com/Paras0750/Bakery_Website/
I am trying to populate orders field but it is showing null.
You are importing csv file with _id value. It will become string in the database instead of ObjectId. That's why it cannot populate. Your code is correct.

Express doesn't get another user with .map()

I came to a problem, where I can create conversations with multiple people 2 and so on. However, I can't understand why it doesn't store data to seperate User models.
Here is a code that you only need to know:
router.post(
"/",
auth,
[
check("conversators", "There should be at least two conversators").isLength(
{ min: 2 }
),
],
async (req, res) => {
const { conversators } = req.body;
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
try {
let conversation = new Conversation({
user: req.user.id,
conversators: conversators,
});
await conversators.map(async (conversator) => {
let user = await User.findById(conversator);
let newData = user;
newData.conversations.push(conversation.id);
console.log('Created data', newData);
let newUser = await User.findOneAndUpdate(
{ user: conversator },
{
$set: {
newData,
},
},
{ new: true }
);
await newUser.save();
console.log(newUser);
});
await conversation.save();
res.status(200).json(conversation);
} catch (error) {
console.error(error.message);
res.status(500).send("Server error.");
}
}
);
module.exports = router;
What I can assure is that this line: console.log('Created data', newData); prints the desired data. However, the next console: console.log(newUser); prints the same User model as the previous one.
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const UserSchema = new Schema({
name: {
type: String,
required: true,
},
surname: {
type: String,
required: true,
},
email: {
type: String,
required: true,
},
password: {
type: String,
required: true,
},
conversations: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "conversation",
},
],
date: {
type: Date,
default: Date.now,
},
});
module.exports = User = mongoose.model("user", UserSchema);
The reason might be the difference in search methods used to get a record for newData and newUser. You have used User.findById for newData, which will obviously return different objects for different ids. But User.findOneAndUpdate uses filter criteria that may satisfy several results, but only first will be returned. So it boldly depends on what that user field is.
Here is the part that I changed and started to see the data on MongoDB:
await conversators.map(async (conversator) => {
let user = await User.findById(conversator);
let newData = user;
newData.conversations.push(conversation.id);
new Promise(async (resolve, reject) => {
user = await User.findOneAndUpdate(
{ id: conversator },
{
$set: {
newData,
},
},
{ new: true }
);
return resolve;
})
return await user.save();
});
Posted on behalf of the question asker

findOneandReplace keeps giving error: "Error: The replacement document must not contain atomic operators."?

I am currently developing a Pokemon Team Builder app with a React frontend and an Express backend with MongoDB for the database.
As far as I can tell my TeamSchema has no such atomic operators? Here is my TeamSchema:
const mongoose = require('mongoose');
const TeamSchema = new mongoose.Schema({
name: {
type: 'String',
required: true,
unique: true,
},
team: [
{
name: { type: String },
types: [{ type: String }],
sprite: { type: String },
},
],
username: {
type: String,
required: true,
},
userId: {
type: String,
required: true,
},
});
const TeamModel = mongoose.model('Team', TeamSchema);
module.exports = TeamModel;
And the error gets thrown in this method when I attempt to call the findOneAndReplace method by finding a team that has a name and userId match.
const replaceTeam = async (req, res) => {
const { teamName: name, filteredTeam: team } = req.body;
const { username, _id: userId } = req.user;
const newTeam = new Team({ name, team, username, userId });
try {
const replacedTeam = await Team.findOneAndReplace({ name, userId }, newTeam);
console.log(replacedTeam);
res.status(200).json({ message: 'Team was successfully overwritten!' });
} catch (err) {
console.log(err);
res.status(500).json({ message: 'An error occurred while updating the team.' });
}
};
This has been a real headscratcher here and I am not sure what is going wrong here. I have only started using mongoose a couple of weeks ago, so I wonder if it's something fundamental I am misunderstanding here.
The Mongoose function findOneAndReplace expects a document object passed in. See the below code.
details.findOneAndReplace(
{ location: "New York" },
{ name: "Sunny", age: 292, location: "Detroit" },
function(err, result) {
if (err) {
res.send(err);
} else {
res.send(result);
}
}
);
Change
const newTeam = new Team({ name, team, username, userId })
to
const newTeam = {name, team, username, userId}
Also as in the other poster's code, add the new: true option to the call as follows by changing
const replacedTeam = await Team.findOneAndReplace({ name, userId }, newTeam);
to
const replacedTeam = await Team.findOneAndReplace({ name, userId }, newTeam, { new: true });
otherwise the original document will be returned into replacedTeam
You can just use findOneAndUpdate and update all the fields with new data. You can do it like this:
const replaceTeam = async (req, res) => {
const { teamName: name, filteredTeam: team } = req.body;
const { username, _id: userId } = req.user;
try {
const replacedTeam = await Team.findOneAndUpdate({ name, userId }, { name, team, username, userId }, {new: true});
console.log(replacedTeam);
res.status(200).json({ message: 'Team was successfully overwritten!' });
} catch (err) {
console.log(err);
res.status(500).json({ message: 'An error occurred while updating the team.' });
}
};

Item.filter is not a function

Hi everyone I am making a route to get the items that are created by the logged-in user but when I use the .filter function I get an error. Not sure why I am getting this error. I have made other apps before doing the same thing and never got an error
Item.filter is not a function
The my-items route
const requireAuth = require("../middleware/requireAuth");
const express = require("express");
const mongoose = require("mongoose");
const Item = mongoose.model("Item");
router.get("/my-items", requireAuth, async (req, res) => {
try {
const items = Item.filter((item) => item.userId === req.user.userId);
res.send(items);
} catch (err) {
console.log(err);
}
});
Item Schema
const mongoose = require("mongoose");
const itemSchema = new mongoose.Schema({
userId: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
},
phone: {
type: mongoose.Schema.Types.String,
ref: "User",
},
email: {
type: mongoose.Schema.Types.String,
ref: "User",
},
seller: {
type: mongoose.Schema.Types.String,
ref: "User",
},
title: {
type: String,
required: true,
},
category: {
type: String,
required: true,
},
detail: {
type: String,
requiredL: true,
},
condition: {
type: String,
required: true,
},
price: {
type: Number,
required: true,
},
});
mongoose.model("Item", itemSchema);
const items = await Item.find(({userId:req.user.userId}).lean();
it should return exact items from db that you want you can use more query if you need.
Item is a model but not the documents in the database, you need to do a query first in order to get the items.
router.get("/my-items", requireAuth, async (req, res) => {
try {
const query = Item.find()
query.exec().then(items => {
const filteredItems = items.filter((item) => item.userId === req.user.userId);
res.send(items);
})
} catch (err) {
console.log(err);
}
});
This error can occur when you are trying to use the array methods on other data structures.
This piece of code returns an error .filter is not a function:
const myList = await getList().filter(item => item.myKey > 10);
Solution:
const data = await getList();
const myList = data.filter(item => item.myKey > 10);

TypeError: User.findByIdAndUpdate is not a function

Answer
this fixed: mongoose.model('User').findByIdAndUpdate(... although it doesn't seem right. Should be another way to require this. Will figure out.
I have a signup form, where user can check a role to either create a candidate or an employer account. Let's say, user picked employer, then mongoose post hook will be triggered to create an employer inside employer collection and return employer._id so that I can save it to user collection as reference. In the last code snippet, findByIdAndUpdate is not triggered and failed silently. Log, outputs only a.
user.js (user model)
const mongoose = require('mongoose');
const { Schema } = mongoose;
const bcrypt = require('bcrypt-nodejs');
const {
updateUserWithEmployerId,
updateUserWithCandidateId
} = require('../api/user');
const { createCandidate } = require('../api/candidate');
const { createEmployer } = require('../api/employer');
const userSchema = new Schema({
firstName: String,
lastName: String,
email: {
type: String,
unique: true,
lowercase: true
},
password: String,
role: {
type: String,
enum: ['candidate', 'employer']
},
_employerId: {
type: Schema.Types.ObjectId,
ref: 'Employer'
},
_candidateId: {
type: Schema.Types.ObjectId,
ref: 'Candidate'
}
}, {
timestamps: true
});
userSchema.post('save', function(doc, next){
if(doc.role === 'employer'){
return createEmployer(doc._id)
.then(response => updateUserWithEmployerId(doc._id, response.employer._id))
// .catch(error => next(error))
// .catch(error => response.status(500).send(error))
}else if(doc.role === 'candidate'){
return createCandidate(doc._id)
.then(response => updateUserWithCandidateId(doc._id, response.candidate._id))
.catch(error => response.status(500).send(error))
}else{
throw new Error('User role not found!');
}
next();
});
const ModelClass = mongoose.model('User', userSchema);
module.exports = ModelClass;
employer.js(this is not model)
const Employer = require('../models/employer');
exports.createEmployer = (userId) => {
return new Promise(function(resolve, reject){
const employerInstance = new Employer({ _userId: userId });
if(employerInstance){
employerInstance.save((err, employer) => {
if(err){
reject({ message: "Error occured while creating employer!" });
}else{
resolve({ employer: employer });
}
});
}else{
reject({ message: "Error occured while creating employer!" });
}
});
};
user.js (not a model)
const User = require('../models/user');
exports.updateUserWithEmployerId = (userId, employerId) => {
return new Promise(function(resolve, reject){
console.log("a");
User.findByIdAndUpdate(userId, { _employerId: employerId }, { new: true },
(err, user) => {
console.log("user:", user);
if(err){
console.log("b");
reject({ message: "Error occured while updating user with employer id!" });
}else{
console.log("c");
resolve({ user: user });
}
});
console.log("d");
});
};
Server is working on http:4000
Mongodb connected with server: localhost
C:\Ajay Vemra\Mern Stack E-Commerce Website\backend\controllers\productController.js:41
product = await product.findByIdAndUpdate(req.params.id,req.body,{
^
TypeError: product.findByIdAndUpdate is not a function
at exports.updateProduct (C:\Ajay Vemra\Mern Stack E-Commerce Website\backend\controllers\productController.js:41:29)

Categories