Related
This is my first post so please bear with me. I am building a LinkedIn clone and I am trying to keep track of the work experience, projects and courses of the users, and those will be kept in an array of objects inside of the User schema. Now let's say a user will try to add or update one of the elements in one of those arrays, I have the user ID and I am passing it to findOneAndUpdate() as the filter.
Here is my User schema:
const userSchema = new mongoose.Schema({
user_id: {
type: String,
required: [true, 'User ID required.'],
unique: true,
immutable: true,
},
name: {
type: String,
required: [true, 'Name required.'],
},
email: {
type: String,
required: [true, 'Email required.'],
unique: true,
lowercase: true,
immutable: true,
},
title: {
type: String,
},
location: {
type: String,
},
phone_number: {
type: String,
},
contact_email: {
type: String,
},
photo: {
type: String,
},
website: {
type: String,
},
backdrop: {
type: String,
},
summary: {
type: String,
},
work: {
type: String,
},
connections: {
type: Number,
},
projects: [
{
title: {
type: String,
},
description: {
type: String,
},
start_date: {
type: Date,
},
end_date: {
type: Date,
},
technologies: {
type: String,
},
picture: {
type: String,
},
},
],
skills: [{
skill: {
name: {
type: String,
},
level: {
type: String,
},
},
}],
experience: [
{
company: {
type: String,
},
logo: {
type: String,
},
title: {
type: String,
},
location: {
type: String,
},
start_date: {
type: Date,
},
end_date: {
type: Date,
},
description: {
type: String,
},
},
],
education: [
{
school: {
type: String,
},
logo: {
type: String,
},
degree: {
type: String,
},
location: {
type: String,
},
start_date: {
type: Date,
},
end_date: {
type: Date,
},
description: {
type: String,
},
},
],
languages: [
{
name: {
type: String,
},
level: {
type: String,
},
},
],
awards: [
{
title: {
type: String,
},
date: {
type: Date,
},
awarder: {
type: String,
},
summary: {
type: String,
},
},
],
courses: [
{
title: {
type: String,
},
number: {
type: String,
},
school: {
type: String,
},
start_date: {
type: Date,
},
end_date: {
type: Date,
},
description: {
type: String,
},
},
],
});
And in my UserController.ts file, I tried using this:
const updateUser = async (req: Request, res: Response) => {
try {
const filter = { user_id: req.body.user_id };
const update = req.body;
const updatedUser = await User.findOneAndUpdate(filter, update, {
new: true,
upsert: true,
});
res.status(201).json({
status: 'success',
data: {
user: updatedUser,
},
});
} catch (err) {
res.status(400).json({
status: `ERROR: ${err}`,
message: 'error updating user',
});
}
};
And in my request using the format of the schema but that didn't work out as expected. I know mongoose will automatically give it an _id field to each of the individual objects in the array, but again, I have had no luck updating them. I tried sending a PATCH request with this as the body to add a skill like so:
{
"user_id": "xxxxxxxxxxxxxxxx",
"title": "Mr.",
"skills" : {
"name": "Flute",
"level": "Novice"
}
}
And this was the response I got. It created a skill but didnt add the data in the skill object:
{
"status": "success",
"data": {
"user": {
"_id": "63d3715f2ef9698667230a53",
"user_id": "xxxxxxxxxxxxxxxx",
"name": "Jonathan Abitbol",
"email": "yoniabitbol1#gmail.com",
"projects": [],
"skills": [
{
"_id": "63d4068d2df30c9e943e4608"
}
],
"experience": [],
"education": [],
"languages": [],
"awards": [],
"courses": [],
"__v": 0,
"title": "Mr."
}
}
}
Any help on how to add/edit the nested objects would be appreciated.
I have a summary schema with a structure like this
{
sender: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
required: true,
},
summary: {
type: String,
},
sent: {
type: Date,
default: Date.now,
},
}
);
then a convo schema:
NOTE: summary in this schema is an array of objectId, convo returns an array of objects after fetching, sender is in each of the objects gotten after populating the summary field
{
lastMessage: {
type: mongoose.Schema.Types.ObjectId,
ref: "messages",
},
members: {
type: [mongoose.Schema.Types.ObjectId],
ref: "User",
required: true,
},
summary: {
type: [mongoose.Schema.Types.ObjectId],
ref: "summary",
},
gigDetails: {
type: mongoose.Schema.Types.ObjectId,
ref: "Gig",
},
}
I want to populate the sender field in the summary array in the convo schema when fetching it, in addition to the already populated summary field.
How can I do this?
You can do it like this:
ConvoModel.find(filter).populate([{ path: 'summary', populate: { path: 'sender' } }])
// Fetch the convo documents
const convos = await Convo.find()
.populate("summary")
.exec();
// Iterate through the convos array
for (let i = 0; i < convos.length; i++) {
// Iterate through the summary array and populate the sender field in each element
const summaryPromises = convos[i].summary.map(async summary => {
return await summary.populate('sender').execPopulate();
});
// Wait for all promises to resolve
await Promise.all(summaryPromises);
}
I'm trying to fetch the existing sample_mflix database from mongodb. At first I created a model for the movies collection.
This is my schema for movies
const mongoose = require("mongoose");
const movieSchema = new mongoose.Schema(
{
plot: {
type: String,
},
genres: [
{
type: String,
},
],
runtime: {
type: Number,
},
cast: [
{
type: String,
},
],
num_mflix_comments: {
type: Number,
},
title: {
type: String,
},
countries: [
{
type: String,
},
],
released: {
type: Date,
},
directors: [
{
type: String,
},
],
rated: {
type: String,
},
awards: {
wins: {
type: Number,
},
nominations: {
type: Number,
},
text: {
type: String,
},
},
lastupdated: {
type: String,
},
year: {
type: Number,
},
imdb: {
rating: {
type: Number,
},
votes: {
type: Number,
},
id: {
type: Number,
},
},
type: {
type: String,
},
poster: {
type: String,
},
writers: [
{
type: String,
},
],
tomatoes: {
viewer: {
rating: {
type: Number,
},
numReviews: {
type: Number,
},
meter: {
type: Number,
},
},
lastupdated: {
type: Date,
},
},
},
{ collection: "movies" }
);
const movies = mongoose.model("movies", movieSchema);
module.exports = movies;
this is my route to get all the movies from database
movieRoutes.js
const express = require("express");
const router = express.Router();
const movies = require("../models/movieModel");
router.get("/", async (req, res) => {
//res.send("Movie List");
try {
const allmovies = await movies.find({});
res.json(allmovies);
} catch (error) {
res.json(error);
}
});
module.exports = router;
But I'm unable to get any data in Postman. I'm pretty sure that the route is called but Postman loads forever and does not fetch.
How to fix this ?
So, I'm sending data from angular reactive form like:
Angular reactive form UI image
and
Data being sent to backend in browser console image
I have made schema for task as:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
let taskSchema = new Schema({
taskId:{
type:String,
unique:true
},
task:{
type:String,
default:''
},
subTask:[{
type: Schema.Types.ObjectId,
ref: 'SubTask'
}]
}
module.exports = mongoose.model('Task',taskSchema);
Schema for Sub-Task as:
let subTaskSchema = new Schema({
title:String,
subSubTask:[{
type: Schema.Types.ObjectId,
ref: 'SubSubTask'
}]
})
module.exports = mongoose.model('SubTask',subTaskSchema);
Schema for Sub-Sub-Task as:
let subSubTaskSchema = new Schema({
title:String
})
module.exports = mongoose.model('SubSubTask',subSubTaskSchema);
Now,I'm confused about how to save nested array of objects data in mongodb using mongoose?
you can define your schema like this
const userSchema = new mongoose.Schema({
likedBooks: [{
type: mongoose.Types.ObjectId,
ref: 'books'
}],
email: {
type: String,
required: true
},
name: {
type: String,
required: true
}
});
exports.User = mongoose.model('users', userSchema);
then you can populate data by doing
user = User.find({ email: req.body.email }).populate('likedBooks');
here likedBooks contains _id of each book
const bookSchema = new mongoose.Schema({
isbn: {
type: Number,
required: true
},
name: {
type: String,
required: true
},
author: {
type: String,
required: true
},
publisher: {
type: String,
default: ""
},
imageUrl: {
type: String,
required: true
},
description: {
type: String,
default: ""
}
});
exports.Book = mongoose.model('books', bookSchema);
for both schema i have not put _id as it is auto generated by mongodb and it is used as reference
The Object Model should look like this before saving.
{
taskId: 1,
task: 'Do something',
subTask: [{
title: 'Write a essay',
subSubTask: [{
title: 'Collect details to write an essay'
}]
}]
}
Hope it helps...
This is the model I am working with:
name: {
type: String
},
payment: {
id: {
type: String,
required: true
},
cards: [
{
id: {
type: String
},
is_default: {
type: Boolean,
"default": false
}
}
]
}
I want to add a card to the cards array, for example:
card =
id: "some_token"
is_default: true
I am using the update method to push the card to the array, but it won't add the card to the document. Instead, it creates a new document with only those fields:
{
id: "some_token",
is_default: true,
_id: someId
}
Any idea how I can update the actual document I am targeting instead of creating a new document?
Here's my code (using CoffeeScript):
update_where =
payment:
id: "some_id"
update_push =
$push:
'payment.cards':
id: card_token
is_default: false
Customer.update update_where, update_push, {upsert: true}, (err, results) ->
# Do something with the results
Oh… I just noticed my mistake. The problem was in the where statement.
I was doing:
payment:
id: "some_id"
But the right thing to write is the following:
'payment.id': 'some_id'
And it now works!