how do i delete array item in mongodb? - node.js

I want to delete an element according to the value of "noteID" from the note array inside the project schema in mongo db.
Project Schema
endDate: {
type: String,
required: true,
default: Date.now().toString()
},
notes: {
type: [NoteSchema],
required: false
},
users: [{
type: String,
required: false
}]
Note Schema
const NoteSchema = mongoose.Schema({
noteID: {
type: String,
require: true
},
title: {
type: String,
required: true
},
description: {
type: String,
required: true
},
endDate: {
type: Date,
default: Date.now()
},
priority: {
type: String,
default: "low"
}
});
returning json with express
"endDate": "11.11.2021",
"notes": [
{
"endDate": "2022-02-05T08:02:18.166Z",
"priority": "low",
"_id": "61fe2f423667ad054b62f84f",
"noteID": "cb978ec0-7229-4253-9e36-eaaf85b72ae3",
"title": "test note title",
"description": "test note desc"
},
{
"endDate": "2022-02-05T08:02:18.166Z",
"priority": "medium",
"_id": "61fe2f593667ad054b62f851",
"noteID": "760fda9f-e453-4e9c-bc9f-161f38fd29c0",
"title": "test note title 2",
"description": "test note desc 2"
}
],
"users": [],
I want to delete an item from this notes directory using noteID.

Use update with $pull to remove the element from the array by noteID:
db.collection.update({},
{
$pull: {
notes: {
noteID: "cb978ec0-7229-4253-9e36-eaaf85b72ae3"
}
}
})
Explained:
The above query will remove all objects with nodeID: "cb978ec0-7229-4253-9e36-eaaf85b72ae3" from the array of objects notes[]. The operation apply to the first found document in collection. If you need to apply to all documents in collections you need to add the { multi:true } option
playground

Basically you can delete a schema item like that in mongoose.
YourColletionName.findOneAndDelete({ noteID: "cb978ec0-7229-4253-9e36-eaaf85b72ae3" },
function (err, data) {
if (err){
console.log(err)
}
else{
console.log("Removed: ", data);
}
});
If you want to delete with the noteID link on your page you can use req.params.noteID instead of cb978ec0-7229-4253-9e36-eaaf85b72ae3.
Resources:
https://www.geeksforgeeks.org/mongoose-findoneandremove-function/
https://mongoosejs.com/docs/api.html#model_Model.findOneAndDelete

Related

MongoDB does not full text search in array of strings

I try to search in my database and everythig work ok except search on array of strings.
The stored data looks like this:
{
"_id": "634d8af01f5ed9a5b6669e20",
"content": "Some example text",
"heading": "<h1">Domů</h1>",
"slug": "/home",
"title": "Home",
"keyWords": ["one", "two", "three"]
}
This is my Mongoose schema:
{
// _id
// createdAt
// updatedAt
heading: { type: String, required: true }, // <h1>
title: { type: String, required: true, maxLength: 20 }, // text in menu
slug: { type: String, required: true, unique: true },
coverImgPath: { type: String, required: true },
content: { type: String, required: true },
allowUserEditor: { type: Boolean, required: true },
keyWords: { type: [String] },
}
MySchema.index({heading: "text", title: "text", content: "text", keyWords: "text"});
I try to search like this and content or heading works well, but keyWords does not.
db.Article.article.find({
$text: {
$search: req.params.query,
$caseSensitive: false,
$diacriticSensitive: false
}
}).sort({ score: { $meta: "textScore" } }).limit(10).exec();
I tried change .index(keyWords: "text") to .index("keyWords":"text") and it also does not work.

Mongoose update subdocument

I have some posts documents which contains an array of ids of comments. I am trying to update a particular comment based on the post and the comment id and not sure how to go about it. I have tried to use the $set command but I think I missed something and It doesn't work. What I have tried doing.
async function updateComment(req, res){
try{
const post = await PostsModel.findOneAndUpdate(
{"postID": req.params.id, "comments.id": req.params.commentID},
{"$set": {
"comments.$": req.body
}}
).populate("comments");
if (!post){
return res.status(404).json({msg: "No post found"});
}
res.status(200).json({post});
}catch (e) {
res.status(500).json(e.message);
}
}
The structure and schema of the document:
{
"_id": "62b2c3d0e88f58ddd1135bc7",
"title": "aaaa",
"content": "check it out",
"createdAt": "2022-06-22T07:23:34.525Z",
"comments": [
"62b2fe23b15d50b496149128"
],
"postID": 1
}
The schema for both the post and comment:
const CommentSchema = new mongoose.Schema({
username: {
type: String,
required: true,
},
content:{
type: String,
required: true
},
createdAt:{
type: Date,
default: new Date()
},
})
const PostsSchema = new mongoose.Schema({
title: {
type: String,
required: true
},
content: {
type: String,
required: true
},
createdAt:{
type: Date,
default: new Date()
},
comments: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Comment"
}
]
});

How to add an array as different objects mongodb

I'm having some trouble with a post function in nodeJs
I have the next body to post:
{
"_id": "fffff-ggg-jjjjj",
"type": "",
"gamers": [
"Raul Andres",
"Pedro",
"Juan"
]
}
(I shouldn't change the post body)
And this is my Schema:
var gameSchema = new Schema({
_id: {
type: String,
required: true,
trim: true
},
type: {
type: String,
trim: true
},
gamers: [{
name: {
type: String,
required: true,
trim: true
},
playerBet: {
type: Number,
trim: true
}
}],
inProgress: {
type: Boolean,
trim: true
},
});
So clearly i can't just give it the gamers just like that, so i need to get the array given in the POST body and insert every element as name field so i can add it in the collection.
expected output
{
"id": "fffff-ggg-jjjjj",
"gamers": {
"5257b4d6-5c87-4871-93c3-b2b9ce04d706": {
"id": "5257b4d6-5c87-4871-93c3-b2b9ce04d706",
"name": "Raul Andres"
},
"8dda6205-f54c-4643-a017-71b6f0353319": {
"id": "8dda6205-f54c-4643-a017-71b6f0353319",
"name": "Juan"
},
"e5834d8e-5195-41fc-993e-c731dbce4fab": {
"id": "e5834d8e-5195-41fc-993e-c731dbce4fab",
"name": "Pedro"
}
},
"inProgress": false,
"winner": {
"id": "e5834d8e-5195-41fc-993e-c731dbce4fab",
"name": "Pedro"
}
}
router.post('/createGame', async (request, response, next) => {
try {
const { _id, gamers } = request.body;
const data = new gameModel({
_id,
players:{
name: gamers
},
inProgress: true,
});
await data.save();
response.json({
message: 'Game created successfully',
data
});
} catch (error) {
response.status(500).json({
message: error.message,
stack: error.stack
});
}
});
This is the way i was trying to do it but, name expects a String instead of an array
Thank any who can help me
You can create a gamers schema and add the id to the gamerSchema under the gamers key and store the gamers _id to the gamerSchema.gamers array

How to return count array of subdocuments mongoose

I want to get the total amount of comments from Place models and I couldn't find a way to get it because I don't want to populate the comment with GET /places.
This is my place model
const placeSchema = mongoose.Schema(
{
type: { type: String },
english: { type: String },
province_code: { type: String },
district_code: { type: String, required: true },
commune_code: { type: String },
village_code: { type: String },
lat: { type: Number },
lon: { type: Number },
body: { type: String },
images: [{ type: String }],
comments: [{ type: mongoose.Types.ObjectId, ref: Comment }],
},
{
timestamps: {
createdAt: 'created_at',
updatedAt: 'updated_at',
},
}
)
I use this query
data = await Place
.find()
.limit(5)
.skip(0)
.populate('comments')
.exec()
I want to get the response like this
{
"data": [
{
"images": [],
"comments": 6,
"type": "place",
"english": "99Boko",
"province_code": "23",
"district_code": "2302",
"commune_code": "230202",
"village_code": "23020202",
"lat": 135.2039,
"lon": 104.01734762756038,
"body": "<b>This place is really good</b>",
"created_at": "2021-07-20T17:41:52.202Z",
"updated_at": "2021-07-20T17:41:52.202Z",
"id": "60f70ae08e54941530d14c4c"
},
]}
Does anybody know the solution to get this kind of response ?
I have figured out to get the comment length is to use virtual count
placeSchema.virtual('comment_length', {
ref: Comment, // model to use for matching
localField: 'comments', // from `localField` i.e., Place
foreignField: '_id', // is equal to `foreignField` of Comment schema
count: true, //only get the number of docs
})
placeSchema.set('toObject', { virtuals: true })
placeSchema.set('toJSON', { virtuals: true })
and use this query
data = await Place
.find().populate({ path: 'comment_length', count: true })
.exec()

Mongoose not generating _id for subdocument

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]
}

Resources