I'm new to mongoDB and backend stuffs. I've a nested MongoDB model schema. I need to update, delete and add in that nested objects/array. How can I do that ?
How can I delete/add/update item from columns array and resume array.
const userSchema = new Schema({
name: {
type: String,
required: true,
},
email: {
type: String,
required: true,
},
password: {
type: String,
},
columns: [
{
title: {
type: String,
required: true,
},
resumes: [
{
name: {
type: String,
required: true,
},
resume: {
type: String,
required: true,
},
},
],
},
],
});
const Users = mongoose.model('Users', userSchema);
This is my schema
To add new item to the columns array:
let newData = {title: "New Title", resumes: []}
let userData = await User.findByIdAndUpdate(userID, {
$push: {
columns: newData,
},
});
To add new item to the resumes array inside columns:
let newData = {name: "New Name", resume: "New Resume"}
let userData = await User.updateOne(
{
_id: mongoose.Types.ObjectId("60f54774761788cd80f56xxx"),
"columns._id": mongoose.Types.ObjectId("60f54774761788cd80f56xxx"),
},
{
$push: { "columns.$.resumes": newData },
}
);
Similarly, you can use $pull operator to remove an object from the array, and $(update) to update the element inside the array
Related
I want to delete all elements from an array in my document..
I have an array of object id's
My model looks like this:
const TypeSchema = new mongoose.Schema({
ISOklasifikacija: { type: String, requred: false },
profilUIC: { type: String, requred: false },
certificateId: [
{
type: Schema.Types.ObjectId,
ref: "Certificates",
required: false,
},
],
});
My query for clearing the array is:
let type = await Type.findOneAndUpdate(
{
_id: req.params.typeId,
},
{
$set: { certificateId: [] },
},
{ multi: true }
);
console.log(type);
It nevers clear the array. In console I get: null and this id exists which I am passing in
Thanks for help
i am trying to create items to specific id of collection using nodejs and mongoose but i am getting CastError which i shared below picture. So goal is, I binded items id in collection schema because collection has many items and when i create items to the specific id of collection i want to push them to items array in the collection schema.
ERROR
ITEMS ROUTE
itemRouter.post("/:collectionId", JWTAuthMiddleware, async (req, res, next) => {
const {name} = req.body
if (req.params.collectionId.length !== 24)
return next(createHttpError(400, "Invalid ID"));
const collection = await CollectionModal.findByIdAndUpdate(
req.params.collectionId,
{
$push : { items: { ...req.body, owner: req.user._id, id: uuidv4() } },
},
{ new: true }
);
if (!collection)
return next(
createHttpError(
400,
`The id ${req.params.collectionId} does not match any collections`
)
);
res.send(collection);
});
Collection schema
import mongoose from "mongoose";
const { Schema, model } = mongoose;
const collectionSchema = new Schema(
{
name: { type: String },
description: { type: String },
topic: { type: String },
image: { type: String },
additionalCustomFields: {
fieldNumber: { type: Number },
fieldName: { type: String },
fieldType: { type: String },
fieldChecked: { type: Boolean },
fieldDate: { type: Date },
},
owner: { type: Schema.Types.ObjectId, ref: "User" },
items: [{ type: Schema.Types.ObjectId, ref: "Item" }],
},
{ timestamps: true }
);
// collectionSchema.index({ "$**": "text" });
export default model("Collection", collectionSchema);
ITEM schema
import mongoose from "mongoose";
const { Schema, model } = mongoose;
const itemSchema = new Schema(
{
name: { type: String },
description: { type: String },
topic: { type: String },
image: { type: String },
comments: [
{
user: { type: Schema.Types.ObjectId, ref: "User", required: true },
text: { type: String },
},
],
tags: { type: String },
owner: { type: Schema.Types.ObjectId, ref: "User" },
likes: [{ type: Schema.Types.ObjectId, ref: "User" }],
collections: { type: Schema.Types.ObjectId, ref: "Collection" },
},
{ timestamps: true }
);
itemSchema.index({ "$**": "text" });
export default model("Item", itemSchema);
Are you sure that using referenced documents is the correct way to go here? Mongoose is complaining because you are trying to push whole objects to the "items" array, instead of ObjectIds of referenced documents.
You have 2 choices here:
1. use embedded documents
This way you can easily store objects directly to the items array, which does not allow you to store the Items in a seperate collection
2. first create Item documents, then push the reference to items array
In this case you have to first create the items in Item collection. Afterwards you can map the result to only ObjectIds and push these to items array of your collection document.
I have this document in mongo atlas
_id: 5f8939cbedf74e363c37dd86,
firstname: "Person",
lastname: "Person lastname",
sex: "Masculino",
age: "20",
birthDay: 2020-10-07T00:00:00.000+00:00,
vaccines: Array
0:Object
dose: Array
_id: 5f8939cbedf74e363c37dd87
vaccine:5f7023ad96f7ed21e85be521
createdAt:2020-10-16T06:12:27.726+00:00
updatedAt:2020-10-16T06:12:27.726+00:00
1:Object
dose:Array
_id:5f893a9ca98e97188c93fea8
vaccine:5f70259796f7ed21e85be523
2:Object
dose:Array
_id:5f893acda98e97188c93fea9
vaccine:5f7023ad96f7ed21e85be521
This is my mongoose schema
const mySchema = new Schema({
firstname: {
type: String,
required: true,
},
lastname: {
type: String,
required: true,
},
sex: {
type: String,
required: true,
},
age: {
type: String,
required: true,
},
birthDay: {
type: Date,
required: true,
},
vaccines: [
{
type: new Schema(
{
vaccine: {
type: Schema.ObjectId,
ref: "Vaccine",
},
dose: Array,
},
{ timestamps: true }
),
},
],
});
every time I add a new person the vaccines array gets one new object with the timestamp as you can see, in my js file I use this code:
const addPerson = (person) => {
const myPerson= new Model(person);
return myPerson.save();
};
Then when I add a new vaccine for the same person this does not get the timestamp, I'm using this code for that:
const addPersonVaccine = async ({ params, body }) => {
if (!params) return Promise.reject("Invalid ID");
const vaccines = [body];
const foundPerson = await Model.updateOne(
{
_id: params,
},
{
$push: {
vaccines: vaccines,
},
}
);
return foundPerson;
};
This is what my body inside vaccines array has:
[ { vaccine: '5f72c909594ee82d107bf870', dose: 'Primera' } ]
The problem is that I have no results about the next timestamps, as you can see in my mongo atlas document:
1:Object
dose:Array
_id:5f893a9ca98e97188c93fea8
vaccine:5f70259796f7ed21e85be523
2:Object
dose:Array
_id:5f893acda98e97188c93fea9
vaccine:5f7023ad96f7ed21e85be521
Is that the best way to implement timestamps in subdocuments or sub schemas?
I will appreciate your answers, thnks 👏
You can use mongoose schema timestamps options to the inner schemas
const mongoose = require("mongoose");
const forumSchema = new mongoose.Schema(
{
title: { type: String, required: true },
biddings: [
{
type: new mongoose.Schema(
{
biddingId: String,
biddingPoints: Number
},
{ timestamps: true }
)
}
]
},
{ timestamps: true }
);
const Forum = mongoose.model("Forum", forumSchema);
module.exports = Forum;
for more Mongoose schema set timestamp on nested document
I have a simple schema with an array in there. When I create a new item including items in the mapping array, the items in the mapping array are automatically assigned an _id. However, when I try to add items to the mapping array of an existing item, the new mapping is created with an _id of null. How do I get mongoose to generate this _id for me? I can't find it anywhere in the documentation.
My schema is:
{
email: {
type: String,
required: true,
index: true,
},
mapping: [
{
mapToField: {
type: String,
enum: [
"subject",
"location",
"company",
"hours",
"rate",
"startDate",
"endDate",
],
required: true,
},
mapToLabel: {
type: String,
required: true,
},
regex: {
type: String,
required: true,
},
},
],
},
{ timestamps: true }
);
I have tried two ways to add an item to the mapping array but both options result in an item being added without an _id.
Option 1:
let item = await Mappings.findOne({ _id: id });
return await item.mapping.create(mapping);
Option 2:
return await Mappings.update(
{ _id: id },
{ $push: { mapping } },
{ upsert: true }
);
How do I get mongoose to generate an _id for the items in the mapping array?
Try defining mapping as an schema in your User schema file.
const mappingSchema = new mongoose.Schema({
mapToField: {
type: String,
enum: [
"subject",
"location",
"company",
"hours",
"rate",
"startDate",
"endDate",
],
required: true,
},
mapToLabel: {
type: String,
required: true,
},
regex: {
type: String,
required: true,
}
})
And then your main schema becomes
{
email: {
type: String,
required: true,
index: true
},
mappings: [mappingSchema]
}
Hey I have one problem with remove nested array from my database, I would like use findOneAndUpdate and $pull. My point is to remove item from reply array. I try find comments item by _id and remove this reply item, but this not working. Please look on my code below.
my schema
var productSchema = new Schema({
description: [{
type: String,
require: true,
}],
comments: [{
body: {
type: String,
trim: true,
},
author: {
type: String,
},
date: {
type: Date,
},
reply: [{
body: {
type: String,
trim: true,
},
author: {
type: String,
}, date: {
type: Date,
}
}]
}]
});
api
router.put('/dashboard/admin/komentarz/odpowiedz/usun/', function(req, res) {
var currentCourse = req.body._id; // main item id
var deleteReply = req.body.reply; // reply item id
var commentId = req.body.commentId // comments item id
Product.findOneAndUpdate({ _id: currentCourse }, { $pull: { reply: req.body.reply }}, function(err, product){
//some code
})
Take ref from Mongoose, pull from subdocument
Product.findOneAndUpdate({
_id: currentCourse,
// make sure sub document have a unique field let take _id
"comments._id" : 'commentId'
},
{
$pull: {
"comments.$.reply": {
_id:'replyId'
}
}
},
{
upsert:false,
new:true
}, function(err, product){
//some code
})