Mongoose not pushing into an array - javascript

My code is:
Model:
var mongoose = require('mongoose');
var eventSchema = new mongoose.Schema({
'eventTitle': String,
'location': String,
'startDate': String,
'endDate': String,
'startTime': String,
'endTime': String,
'createdBy': mongoose.Schema.Types.ObjectId, // Here we will store the _ID from the user EOSP.
'attendants': {
'seekers': [mongoose.Schema.Types.ObjectId],
'employers': [],
},
'isFinished': {'type': Boolean, 'default': false},
'uploadedResumes': Number,
'downloadedResumes': Number,
'survey': {
'seekers': [],
'employers': [],
'host': [],
}
});
module.exports = mongoose.model('event', eventSchema);
Router:
.post(async (req, res) => {
let {user, params} = req;
let {eid, uid} = params;
eid = mongoose.Types.ObjectId(eid);
uid = mongoose.Types.ObjectId(uid);
user = user ? user : await Account.findById(uid).catch(e => console.log(e));
if (user.accType.toLowerCase() === 'seeker') {
const {
rating,
recommendation,
websiteEaseOfUse,
chatHelpfulness,
skillsSuitability,
tips,
} = req.body;
const data = {
userId: user._id,
rating,
recommendation,
websiteEaseOfUse,
chatHelpfulness,
skillsSuitability,
tips,
};
console.log(data);
Event.findOneAndUpdate({'_id': eid}, {
$push: {
'survey.seeker': {
userId: user._id,
rating,
recommendation,
websiteEaseOfUse,
chatHelpfulness,
skillsSuitability,
tips,
},
},
}, {$upsert: true,}).then(r => console.log('pushed', r.survey.seekers)).catch(e => console.log(e));
}
const title = await Event.findById(eid).then(r => r.eventTitle).catch(e => console.log(e));
const event = await functions.getCurrentEvent();
res.render('survey/thanks', {
title: title,
user: user,
event: event
})
});
So what this code should do, is take the data passed to the router via post (This actually works), and push it into an array (This doesn't work).
Here's the log:
pushed []
So my question is why even though the console says it passed, (console.log('push')), it doesn't put the data in there? What am I missing?

You are using the wrong key, use survey.seekers instead of survey.seeker
.post(async (req, res) => {
let {user, params} = req;
let {eid, uid} = params;
eid = mongoose.Types.ObjectId(eid);
uid = mongoose.Types.ObjectId(uid);
user = user ? user : await Account.findById(uid).catch(e => console.log(e));
if (user.accType.toLowerCase() === 'seeker') {
const {
rating,
recommendation,
websiteEaseOfUse,
chatHelpfulness,
skillsSuitability,
tips,
} = req.body;
const data = {
userId: user._id,
rating,
recommendation,
websiteEaseOfUse,
chatHelpfulness,
skillsSuitability,
tips,
};
console.log(data);
Event.findOneAndUpdate({'_id': eid}, {
$push: {
'survey.seekers': {
userId: user._id,
rating,
recommendation,
websiteEaseOfUse,
chatHelpfulness,
skillsSuitability,
tips,
},
},
}, {$upsert: true,}).then(r => console.log('pushed', r.survey.seekers)).catch(e => console.log(e));
}
const title = await Event.findById(eid).then(r => r.eventTitle).catch(e => console.log(e));
const event = await functions.getCurrentEvent();
res.render('survey/thanks', {
title: title,
user: user,
event: event
})
});

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

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);

Mongoose: How to post into array inside Schema

I have a Company Schema that will hold some data for that company and an array of posts. When a user submits a post I use passport to decode the token and get some user information. Inside that user information there is an object ID which allows me to find the company that the user belongs to.
So now I have found the company that the user belongs to I need to save the submitted post into the board_posts array inside this company
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const BoardPostSchema = new Schema({
name: {
type: String
}
});
const CompanySchema = new Schema({
company_name: {
type: String
},
board_posts: [BoardPostSchema],
});
module.exports = Company = mongoose.model('companies', CompanySchema);
router.post('/new-opportunity', passport.authenticate('jwt', {
session: false
}), (req, res) => {
let user = req.user;
let newPost = req.body;
let companyId = user.company_id;
const boardPost = {
name: newPost.name
};
Company.find({'_id': companyId})
.then(company => {
// push boardPost into this company.board_posts array
})
.catch(error => {
});
});
An alternative solution with findByIdAndUpdate:
router.post("/new-opportunity", passport.authenticate("jwt", { session: false }), (req, res) => {
let user = req.user;
let newPost = req.body;
let companyId = user.company_id;
const boardPost = {
name: newPost.name,
};
Company.findByIdAndUpdate(
companyId,
{
$push: {
board_posts: boardPost,
},
},
{
new: true,
}
)
.then((company) => {
console.log("Updated compay if found:", company);
res.send(company);
})
.catch((error) => {
console.log(error);
res.status(500);
});
});
Or if you want only update status, you can use updateOne:
router.post("/new-opportunity", passport.authenticate("jwt", { session: false }), (req, res) => {
let user = req.user;
let newPost = req.body;
let companyId = user.company_id;
const boardPost = {
name: newPost.name,
};
Company.updateOne(
{ _id: companyId },
{
$push: {
board_posts: boardPost,
},
}
)
.then((result) => {
console.log(result);
// result.n; // Number of documents matched
// result.nModified; // Number of documents modified
res.send(result);
})
.catch((error) => {
console.log(error);
res.status(500);
});
});
You can use $push and update
router.post('/new-opportunity', passport.authenticate('jwt', {
session: false
}), (req, res) => {
let user = req.user;
let newPost = req.body;
let companyId = user.company_id;
const boardPost = {
name: newPost.name
};
Company.update({_id: user.company_id},{
$push{
//the things you want to add
}
});
});
Hopefully this is what you want to do!
Yes you can use the $pushand findOneAndUpdate operator. It would look nicer if you use the async/await approach.
router.post('/new-opportunity', passport.authenticate('jwt', {
session: false
}), async (req, res) => {
let user = req.user;
let newPost = req.body;
let companyId = user.company_id;
const boardPost = {
name: newPost.name
};
let response = await Company.findOneAndUpdate({'_id': companyId}, {
$push: {
board_posts: "testword1"
}
},{ new: true }) //i set this to true so mongodb will return me the new updated document
res.send(response);
});

Mongoose assign a collection to another

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.

Categories