The given below is my document, I need to remove comments array of an object from the document, so I can pass the document id from the frontend, with postId.
I am struct please help me.
{
likes: [],
_id: 5ea4375f49e4355094073330,
title: 'abc',
body: 'abc',
photo: 'no pic',
postedBy: 5e9aa457de91831e5c9f5005,
comments: [
{
_id: 5ea437c2a584ce5ac0147da1,
text: 'sadsadsad',
postedBy: [Object]
},
{
_id: 5ea437c5a584ce5ac0147da2,
text: 'sadsadsad',
postedBy: [Object]
},
{
_id: 5ea437c7a584ce5ac0147da3,
text: 'sadsadsad',
postedBy: [Object]
}
],
__v: 0
}
If you want to remove a specific element from the array of comments you can use the following query:
db.mycollection. updateOne(
{'_id': ObjectId("5ea4375f49e4355094073330")},
{ $pull: { "comments" : { _id: ObjectId("5ea437c2a584ce5ac0147da1") } } }
);
If you want to remove comment object from every element in your collection you can simply remove the first argument from update. Something like this:
db.mycollection.updateMany(
{ },
{ $pull: { "comments" : { _id: ObjectId("5ea437c2a584ce5ac0147da1") } } }
);
Related
I have an array of the id which I get from post request in nodejs. I want to remove all the elements in the orders array which match receive id array.
eg remove_id = ['60f1ab20891ced4818b5ea88','60f1ab20891ced4818b5ea87']
so I want to remove all elements from orders array whoose id match match remove_id array.
orderdetail = {
_id: 60f1ab20891ced4818b5ea86,
totalPrice: 400,
orders: [
{
_id: 60f1ab20891ced4818b5ea87,
quantity: 1,
price: 200,
name: 'Caramel Latte',
category: 'Steaming Cups'
},
{
_id: 60f1ab20891ced4818b5ea88,
quantity: 1,
price: 200,
name: 'Cinnamon Latte',
category: 'Steaming Cups'
},
{
_id: 60f1ab20891ced4818b5ea89,
quantity: 1,
price: 200,
name: 'Cinnamon Latte',
category: 'Steaming Cups'
}
],
timestamp: 1626450720332,
name: 'xxx',
email: 'xxx',
}
what I have tried but not working,
Orderdetail.updateOne( { _id: '60f1ab20891ced4818b5ea86' }, {
$pull: { order: { _id: { $in: remove_id } } } } )
Rename object name order to orders !
Try this code !
let remove_id = ['60f1ab20891ced4818b5ea87','60f1ab20891ced4818b5ea88']
db.getCollection('Orderdetail').updateOne({ _id: '60f1ab20891ced4818b5ea86' }, {
$pull: {
orders: { // rename this to orders
_id: { $in: remove_id }
}
}
})
I'm trying to get an array of objects with the matching id's and with only sub-array product_price object with matching attributes size and model?
product_name: {
type: String,
required: true,
},
service_hourly_price: {
type: Number,
required: true
},
product_price: [{
model:{
type: String,
enum:['Euro','Japanese']
},
size:{
type: String,
enum: ['S','M','L','XL']
},
price:{
type: Number,
required: true,
}
}],
Trying to query like this:
ProductSchema.aggregate( [
{$match: { _id: {
$in: _id.map(function(_id){ return new mongoose.Types.ObjectId(_id) })
}}},
{ $match : { product_price : {model : 'Euro' , size: 'S'}}}
])
how can I achieve result like this:
products:{
_id: new ObjectId("61b3ab3ceba5bc724d754929"),
product_name: 'Basic Service',
service_hourly_price: 25,
product_price: [
{
_id: new ObjectId("61b3ab3ceba5bc724d75492a"),
size: 'S',
model: 'Euro',
price: 100
}
]
},
{
_id: new ObjectId("61b3aa88eba5bc724d7548fb"),
product_name: 'Horn',
service_hourly_price: 5,
product_price: [
{
_id: new ObjectId("61b3aa88eba5bc724d7548fc"),
size: 'S',
model: 'Euro',
price: 110
}
]
}
product_price must contain only one matching object in it.
I am uncertain why your product_prize is an array with only one object, you could remove the array there, and thus remove the $unwind in the aggregation, but nontheless this works for you right now:
ProductSchema.aggregate( [
{$match: {
_id: {
$in: _id.map(function(_id){ return new mongoose.Types.ObjectId(_id) })
}}}, {
'$unwind': {
'path': '$product_price'
}
}, {
'$match': {
'product_price.model': 'Euro',
'product_price.size': 'S'
}
}
])
Here try it out
Here the proof with the mongo Compass:
I have a Schema of Project that looks like this:
const ProjectSchema = new mongoose.Schema({
name: {
type: String,
Required: true,
trim: true
},
description: {
type: String,
},
devices: [{
name: {type: String, Required: true},
number: {type: String, trim: true},
deck: {type: String},
room: {type: String},
frame: {type: String}
}],
cables: {
type: Array
},
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
adminsID: {
type: Array
},
createdAt: {
type: Date,
default: Date.now
}
I want to query an object from array of "devices".
I was able to add, delete and display all sub-documents from this array but I found it really difficult to get single object that matches _id criteria in the array.
The closest I got is this (I'm requesting: '/:id/:deviceID/edit' where ":id" is Project ObjectId.
let device = await Project.find("devices._id": req.params.deviceID).lean()
console.log(device)
which provides me with below info:
[
{
_id: 6009cfb3728ec23034187d3b,
cables: [],
adminsID: [],
name: 'Test project',
description: 'Test project description',
user: 5fff69af08fc5e47a0ce7944,
devices: [ [Object], [Object] ],
createdAt: 2021-01-21T19:02:11.352Z,
__v: 0
}
]
I know this might be really trivial problem, but I have tested for different solutions and nothing seemed to work with me. Thanks for understanding
This is how you can filter only single object from the devices array:
Project.find({"devices._id":req.params.deviceID },{ name:1, devices: { $elemMatch:{ _id:req.params.deviceID } }})
You can use $elemMatch into projection or query stage into find, whatever you want it works:
db.collection.find({
"id": 1,
"devices": { "$elemMatch": { "id": 1 } }
},{
"devices.$": 1
})
or
db.collection.find({
"id": 1
},
{
"devices": { "$elemMatch": { "id": 1 } }
})
Examples here and here
Using mongoose is the same query.
yourModel.findOne({
"id": req.params.id
},
{
"devices": { "$elemMatch": { "id": req.params.deviceID } }
}).then(result => {
console.log("result = ",result.name)
}).catch(e => {
// error
})
You'll need to use aggregate if you wish to get the device alone. This will return an array
Project.aggregate([
{ "$unwind": "$devices" },
{ "$match": { "devices._id": req.params.deviceID } },
{
"$project": {
name: "$devices.name",
// Other fields
}
}
])
You either await this or use .then() at the end.
Or you could use findOne() which will give you the Project + devices with only a single element
Or find, which will give you an array of object with the _id of the project and a single element in devices
Project.findOne({"devices._id": req.params.deviceID}, 'devices.$'})
.then(project => {
console.log(project.devices[0])
})
For now I worked it around with:
let project = await Project.findById(req.params.id).lean()
let device = project.devices.find( _id => req.params.deviceID)
It provides me with what I wanted but I as you can see I request whole project. Hopefuly it won't give me any long lasting troubles in the future.
I'm trying to setup a delete button where a lesson can be deleted from a class. Using $pull seems to just set lesson_id to null though. Is there a way to remove that element completely?
var classSchema = new Schema({
title: { type: String, required: true },
lessons: [{
_id: false,
lesson_id: {type: mongoose.Schema.Types.ObjectId, ref: 'Lesson'}
}]
});
module.exports.deleteLesson = function(class_id, lesson_id, callback){
Class.update(
{'_id': class_id},
{ $pull: {lessons: {'lesson_id.$._id': lesson_id}}},
callback
)
}
For example
{ _id: 5808,
title: 'cd',
__v: 0,
lessons: [ { lesson_id: [Object] }, { lesson_id: [Object] } ] }
becomes
{ _id: 5808,
title: 'cd',
__v: 0,
lessons: [ { lesson_id: null }, { lesson_id: [Object] } ] }
If you need to delete an element from lessons (which is an array), then you need to just perform the deletion of element from the array and then perform a save operation. I have written code showcasing a similar approach.
Class.findOne({ _id: class_id }, function(err, cls) {
# Delete the element (for example, using underscore)
cls.lessons = _.without(cls.lessons, class_id);
cls.save(function (err) {
callback(err);
});
});
I have the following collection definition:
// Includes
import mongoose from 'mongoose';
const Schema = mongoose.Schema;
// Create required sub schemas
const subSchema0 = new Schema({
value: String,
});
const subSchema = new Schema({
idWordsLibraryName: {
type: Schema.Types.ObjectId,
ref: 'WordsLibrary1_0',
},
type: String,
values: [
subSchema0,
],
});
const schema = new Schema({
version_: String,
idWordsLibraryName: {
type: Schema.Types.ObjectId,
ref: 'WordsLibrary1_0',
},
idsDads: [{
type: Schema.Types.ObjectId,
ref: 'LocationStructure1_0',
}],
params: [
subSchema,
],
});
Summary -> One document with nested parameters with nested values.
I have the following request that add some values into a particular parameter
this.findOneAndUpdate({
_id: data.idLocationStructure,
'params._id': data.idLocationStructureParameter,
}, {
$push: {
'params.$.values': {
$each: dataToPush,
},
},
}, {
new: true,
});
It works as expected.
What I want now is to get the _id of pushed elements, but without loading all values of the parameter.
I have tried to use the select option of findOneAndUpdate but it don't work using the projection:
this.findOneAndUpdate({
_id: data.idLocationStructure,
'params._id': data.idLocationStructureParameter,
}, {
$push: {
'params.$.values': {
$each: dataToPush,
},
},
}, {
new: true,
select: {
'params.$.values': 1,
},
});
It gets me:
{
"_id": "57273904135f829c3b0739dd",
"params": [
{},
{},
{},
{},
],
},
I have tried to perform a second request to get the _ids as well, but it don't work either:
this.find({
_id: data.idLocationStructure,
'params._id': data.idLocationStructureParameter,
}, {
_id: 1,
'params.$.values': {
$slice: -nbAdded,
},
});
If you have any idea of how retrieving the _id of the pushed values without loading all values of the parameter, you are very welcome :)
Well after tons of researches all over the web and stack overflow <3 I have found a solution, which is:
this.aggregate([{
$match: {
_id: new mongoose.Types.ObjectId(data.idLocationStructure),
},
},
{
$unwind: '$params',
}, {
$match: {
'params._id': new mongoose.Types.ObjectId(data.idLocationStructureParameter),
},
},
{
$unwind: '$params.values',
},
{
$sort: {
'params.values._id': -1
},
},
{
$limit: nbAdded,
},
{
$project: {
_id: '$params.values._id',
},
},
]);
If you experience the same problem, here is the explaination:
$match makes me taking the good high level document
$unwind makes me to go into the params array in the document we $match
$match makes me taking the good parameter
$unwind makes me to go into the values array
I $sort all values by _id DESC
I $limit to the number of values I added previsoulsy
I change the name of the _id (like an alias)
So I got as result an array that contains the last added values _ids