manage and remove objectId from array - mongoose - node.js

i have this schema structure
{
"_id": {
"$oid": "571251dae4b065a8c4d70ce1"
},
"email": "somthing12345#gmail.com",
"events": [
{
"$oid": "57125378e4b065a8c4d70d10"
},
{
"$oid": "571253b8e4b065a8c4d70d1b"
}
],
"valid": true,
}
and my problem is this part
"events": [
{
"$oid": "57125378e4b065a8c4d70d10"
},
{
"$oid": "571253b8e4b065a8c4d70d1b"
}
]
how to remove object in this structure?
can i add fields to each one of thos "events" objects like-
"title" : "some string".
how should i add this?
thanks.

For removing:
events.update({
_id: "571251dae4b065a8c4d70ce1"
}, {
$pull: {
events: {
$oid: "57125378e4b065a8c4d70d10"
}
}
}, {
safe: true
}, function(err, obj) {
// code goes here
});
And what about adding field title: "some string", mondoDB at this moment doesn't allow multiple update for embedded documents, so the only one way to achieve your goal is select document from db, then take this document events array and add title to each object of array. save whole document whith changed events array. Hope you understand everything :)

Related

How to update a nested array field inside another nested array in mongo DB using Mongoose Node JS

There is a document that has a nested array inside a nested array. In one of the cases, I want to update the child array of child array.
{
"_id": "62da8472669b750870b094f6",
"name": "Test Expert",
"user_id": "62bdabee9aa50c0028d60767",
"services": [
{
"service_name": "Hello 2",
"service_id": "62ce7393534bda04d40f42c3",
"_id": "62ce7394534bda04d40f42c4",
"videos": [
{
"_id": "62da8472669b750870b094f8",
"lv_guid_id": "fsdfdshflsdhj",
"status": "REQUESTED" //Need to update this element status
},
{
"_id": "62da8472669b750870b09sdw",
"lv_guid_id": "gdfgdfgfdg",
"status": "REQUESTED" //Need to update this element status
}
]
}
],
"__v": 0
}
In this above document, I want to update the element inside videos array and this videos array are nested array of services array.
This is what I tried but I couldn't get the second nested array position.
this.findOneAndUpdate(
{ _id: new mongoose.Types.ObjectId(orderID), "services._id": new mongoose.Types.ObjectId(videoDetail.service_id), "services.videos.lv_guid_id": videoDetail.lv_guid_id },
{
$set: {
"services.$.videos./*Need to fetch the position of this element to update*/.status": videoDetail.status
}
},
{ upsert: true, new: true }
);
You can use arrayFilters condition,
create a variable v and check the condition for lv_guid_id
this.findOneAndUpdate(
{
_id: new mongoose.Types.ObjectId(orderID),
"services._id": new mongoose.Types.ObjectId(videoDetail.service_id)
},
{
$set: { "services.$.videos.$[v].status": videoDetail.status }
},
{
arrayFilters: [{ "v.lv_guid_id": videoDetail.lv_guid_id }],
upsert: true,
new: true
}
)
Playground
Note: you can not upsert sub document/array element
All you have to do is "services.$.videos.$.status" if I get you right. Give it a try.
this.findOneAndUpdate(
{ _id: new mongoose.Types.ObjectId(orderID), "services._id": new mongoose.Types.ObjectId(videoDetail.service_id), "services.videos.lv_guid_id": videoDetail.lv_guid_id },
{ $set: { "services.$.videos.$.status": videoDetail.status } },
{ new: true },
)

Replace array of objects with another in Mongo DB

I need to replace members array data with new array of objects mems given below.
{
"name": "Test Group",
"members": [{
'userId': {
$oid: 'fjkfkffy'
},
name: 'Himanshu'
}],
"athletes": [],
"leads": []
}
Here I want to replace members array of object with new array of objects. I basically need to overwrite that members array. I've been trying to do something like this below, but I got an error. Can anyone please help me out?
const mems = [{
"user": {
"$oid": "6093a4a709cc0b000d31ber8",
},
"role": "manager"
},
{
"user": {
"$oid": "60a3aea6ecbf4398f01aa598"
},
"role": "user"
}
];
entities.findOneAndUpdate({
_id: ObjectID(entityID),
"groups._id": ObjectID(groupID)
}, {
$set: {
'groups.$.name': name,
'groups.$.members': mems
}
}, {
'new': true
});

Add new field to a specific object in mongoDB

I want to add a new field to a an object after i search the specific object,
Database looks like this:
{
"_id": {
"$oid": "608378ef1ae6b1368c6220c6"
},
"username": "paul",
"password": "cacavaca123",
"question": "q1",
"answer": "cutu"
}
{
"_id": {
"$oid": "6084c1b557f2242bcc629440"
},
"username": "mircea",
"password": "123456",
"question": "q1",
"answer": "cutu"
}
And i want to search in db for the object with username: paul and add a new field friends:[alex], I have tried this but its not working:
MongoClient.connect(uri, function(err, db) {
var dbc = db.db("chat");
dbc.collection("accounts").find({username: { $eq: user}}).aggregate( [
{
$addFields: {
frequent:[new_friend]
}
}
])
db.close();
});
Also if you know, can you tell me how to update that array of friends and add a new friend to that array?
You've to use update query to do so
Read - updateOne
Demo - https://mongoplayground.net/p/mrTg0DKtnrW
db.collection.update(
{ "username": "paul" },
{
$set: {
friends: ["alex" ]
}
})
Aggregation demo - https://mongoplayground.net/p/yiJgkrgdeHZ

How can i get populate my elements name from an array in mongoose with objectid

I'm trying to show the "name" from the "books" collection , what i'm trying to do is get "bookId" with req.paramsbookId and show it in the "history" array instead of bookId itself, thanks for any help
Method: localhost:3000/users/5f0da88156a370091499406f/borrow/5f0cd134fa4ada27787a5d85
exports.borrowBook=asyncHandler(async(req,res,next)=>{
if (req.params.bookId && req.params.id) {
bookId=req.params._id;
userId=req.params.id;
console.log("userid:"+userId);
const bookName=req.params.bookId;
User.findByIdAndUpdate( userId,{ "$push": { history: {"name":bookName} } },{new:true}).exec();
}
res.status(200).json({success:true,msg:'borrow book'});
})
Here is my books collections
{
"_id": {
"$oid": "5f0cd134fa4ada27787a5d85"
},
"name": "test",
"createdAt": {
"$date": "2020-07-13T21:25:08.261Z"
},
"slug": "test",
"__v": 0
}
This is my users collection
{
"name": "Esin Öner",
"history": [{
"name": ["5f0cd134fa4ada27787a5d85"],
"_id": {
"$oid": "5f0daa930643d71380071627"
}
}, {
"name": ["5f0cd134fa4ada27787a5d85"],
"_id": {
"$oid": "5f0dbca1c0402b1aa472b218"
}
}],
"__v": 0
}
For inserting the book name instead of book id in the history array of users document, you would require to first find the book on the basis of the bookId.
And then use the findOneAndUpdate method to update the history array of the user's document.
Also, there is an issue with your implementation of findOneAndUpdate method. The first argument of findOneAndUpdate method is an object instead of a parameter (reference).
You need to make the following changes to get the desired outcome:
exports.borrowBook=asyncHandler(async(req,res,next)=>{
try {
if (req.params.bookId && req.params.id) {
bookId=req.params._id;
userId=req.params.id;
console.log("userid:"+userId);
const bookName=req.params.bookId;
const bookRecord = await Books.find({"_id": bookId});
await User.findByIdAndUpdate( {"_id": userId},{ "$push": { history: {"name":bookRecord.name} } },{new:true}).exec();
}
} catch(e) {
console.log(e);
res.status(400).send(e);
}
res.status(200).json({success:true,msg:'borrow book'});
})

findOne() returns entire document, instead of a single object

I'm trying to query this set of data using findOne():
{
"_id": {
"$oid": "5c1a4ba1482bf501ed20ae4b"
},
"wardrobe": {
"items": [
{
"type": "T-shirt",
"colour": "Gray",
"material": "Wool",
"brand": "Filson",
"_id": "5c1a4b7d482bf501ed20ae4a"
},
{
"type": "T-shirt",
"colour": "White",
"material": "Acrylic",
"brand": "H&M",
"_id": "5c1a4b7d482bf501ed20ae4a"
}
]
},
"tokens": [],
"email": "another#new.email",
"password": "$2a$10$quEXGjbEMX.3ERdjPabIIuMIKu3zngHDl26tgRcCiIDBItSnC5jda",
"createdAt": {
"$date": "2018-12-19T13:46:09.365Z"
},
"updatedAt": {
"$date": "2018-12-19T13:47:30.123Z"
},
"__v": 2
}
I want to return a single object from the items array using _Id as a filter. This is how I'm doing that:
exports.deleteItem = (req, res, next) => {
User.findOne({ 'wardrobe.items': { $elemMatch: { "_id": "5c1a4b7d482bf501ed20ae4a",} } }, (err, item) => {
console.log(item);
if (err) {
return console.log("error: " + err);
}
res.redirect('/wardrobe');
});
};
However, console.log(item) returns the whole document—like so:
{ wardrobe: { items: [ [Object], [Object] ] },
tokens: [],
_id: 5c1a4ba1482bf501ed20ae4b,
email: 'another#new.email',
password:
'$2a$10$quEXGjbEMX.3ERdjPabIIuMIKu3zngHDl26tgRcCiIDBItSnC5jda',
createdAt: 2018-12-19T13:46:09.365Z,
updatedAt: 2018-12-19T13:47:30.123Z,
__v: 2 }
I want to eventually use this to delete single items, so I need to filter to the single object from the subdocument.
Concerning your question:
MongoDB always returns the full object matching your query, unless you add a projection specifying which fields should be returned.
If you really want to only return a nested object, you could use the aggregation pipeline with the $replaceRoot operator like this:
User.aggregate([
// you can directly query for array fields instead of $elemMatching them
{ $match: { 'wardrobe.items._id': "5c1a4b7d482bf501ed20ae4a"}}},
// this "lifts" the fields wardrobe up and makes it the new root
{ $replaceRoot: {newRoot: '$wardrobe'}
// this "splits" the array into separate objects
{ $unwind: '$items'},
// this'll remove all unwanted elements
{ $match: { 'items._id': "5c1a4b7d482bf501ed20ae4a" },
},
])
This should return only the wanted items.
A note though: If you plan to remove elements from arrays anyways, I'd rather suggest you have a look at the $pull operation, which can remove an element from an array if it matches a certain condition:
https://docs.mongodb.com/manual/reference/operator/update/pull/
User.update(
{ 'wardrobe.items._id': "5c1a4b7d482bf501ed20ae4a"},
{ $pull: { 'wardrobe.items': {_id: "5c1a4b7d482bf501ed20ae4a"}},
{ multi: true }
)

Resources