How to remove subdocument (by Id) embedded in sub array in MongoDB? - mongodb

ProductCollection:
{
_id: { ObjectId('x1')},
products: [
{ listPrice: '1.90', product: {id: 'xxx1'} },
{ listPrice: '3.90', product: {id: 'xxx2'} },
{ listPrice: '5.90', product: {id: 'xxx3'} }
]
},
{
_id: { ObjectId('x2')},
products: [
{ listPrice: '2.90', product: {id: 'xxx4'} },
{ listPrice: '4.90', product: {id: 'xxx5'} },
{ listPrice: '5.90', product: {id: 'xxx6'} }
]
},
I want to remove subdocument (xxx3) from collection (x1), and try below:
ProductCollection.update(
{
"_id": mongoose.Types.ObjectId('x1')
},
{
$pull : { 'products.product': {id: 'xxx3' } }
}
It just doesn't seem to work. Can anyone please help me? Thank you

The field for $pull needs to be the array.
This should work:
$pull: { products: { 'product.id': 'xxx3' } }

add this _id: {id: false} while creating mongoose schema
for eg:
partners:[{
name: { type: String, default: '' },
logo: { type: mongoose.Schema.Types.Mixed, default: '' },
_id: { id: false }
}],

Related

mongoDB: update nested array element

I have the following datastructure
{
_id: ObjectId('61ae12bfb8047effd0ac2a01'),
data: [
{
xml: {
messageId: 1638798015073,
xmlString: 'someXML'
},
data: [
{
customerId: 123456,
validation: {
isValid: true,
message: ''
},
docs: [
{
objectId: 'PA1106:zt:bb302216879669b58c141b12dcdd5eb0',
writtenBack: false
}
]
},
{
customerId: 55555,
validation: {
isValid: true,
message: ''
},
docs: [
{
objectId: 'PA1106:zt:bb302216879669b58b143ef38c016217',
writtenBack: true
}
]
}
]
},
{
xml: {
messageId: 1638798015094,
xmlString: 'someXML'
},
data: [
{
customerId: 55555,
validation: {
isValid: true,
message: ''
},
docs: [
{
objectId: 'PA1106:zt:bb302216879669b58c1416129062c2d2',
writtenBack: false
},
{
objectId: 'PA1106:zt:b8be9ea04011c2a18c148a0d4c9d6aab',
writtenBack: true
}
]
},
]
},
],
createdAt: '2021-12-06T13:40:15.096Z',
createdBy: 'Test'
}
Now I want to update the writtenBack property of for a given Document and objectId. How would I write a query for this?
my updateOne looked like this
{
_id: '61ae12bfb8047effd0ac2a01',
'data.data.docs.objectId': 'PA1106:zt:bb302216879669b58b143ef38c016217'
},
{
$set: { 'data.data.docs.$.writtenBack': true }
}
I know there is arrayFilters for nested arrays, but as far as I know, I need a unique identifier for each array-Level. But I only have the objectId which is unique for a Document. Any Ideas?
Yes, you can achieve the update for the document in the nested array with positional operator $[] and arrayFilters.
db.collection.update({
_id: "61ae12bfb8047effd0ac2a01",
},
{
$set: {
"data.$.data.docs.$[doc].writtenBack": true
}
},
{
arrayFilters: [
{
"doc.objectId": "PA1106:zt:bb302216879669b58b143ef38c016217"
}
]
})
Sample Mongo Playground
I made it work with this query
{
_id: '61ae12bfb8047effd0ac2a01',
},
{
$set: { 'data.$[elem1].data.$[elem2].docs.$[elem3].writtenBack': true }
},
{
arrayFilters: [
{ 'elem1.xml.messageId': 1638798015094 },
{ 'elem2.customerId': 55555},
{ 'elem3.objectId': 'PA1106:zt:bb302216879669b58c1416129062c2d2'}]
}

how to retrive single element of a nested array in mongodb?

let's say i have documents like this in my mongodb:
{
id: 1,
names: [
{
id: 2,
first: [
{
id: 3,
name: "alice",
},
{
id: 4,
name: "bob",
},
]
},
{
id: 5,
first: [
{
id: 6,
name: "berhe",
},
{
id: 7,
name: "belay",
},
]
}
]
}
{
id: 8,
names: [
{
id: 9,
first: [
{
id: 10,
name: "gemechu",
},
{
id: 11,
name: "samy",
},
]
},
{
id: 12,
first: [
{
id: 13,
name: "helen",
},
{
id: 14,
name: "natu",
},
]
}
]
}
now how to retrieve a value with
id=8,
names.id = 9,
names.first.id=10
which is like this:
{
id:10,
name:"gemechu"
}
$match to filter documents by all conditions using $elemMatch,
$unwind deconstruct names array
$match names id condition
$unwind deconstruct first array
$match first id condition
$project to format result
db.collection.aggregate([
{
$match: {
id: 8,
names: {
$elemMatch: {
id: 9,
"first.id": 10
}
}
}
},
{ $unwind: "$names" },
{ $match: { "names.id": 9 } },
{ $unwind: "$names.first" },
{ $match: { "names.first.id": 10 } },
{
$project: {
id: "$names.first.id",
name: "$names.first.name"
}
}
])
Playground

Mongo DB complex query

I need some help with MongoDB.
I Have Ex Schema and Database as below:
`
Tb:
User:
{
name: { type: String }
image: { type: String }
city: { type: String }
address: [{
index: { type: Number }
district_id: { type: Schema.ObjectId, ref: 'District' }
}]
}
Tb2:
District:{
name: { type: String }
code: { type: String }}
Example Database:
User: [{
_id: '1234'
name: 'Jacky',
image: '',
city: 'Da Nang',
address: [
{
index: 1,
district_id: '12345'
},
{
index: 2,
district_id: '123456'
},
{
index: 3,
district_id: '1234567'
}
]
}]
District: [
{
_id: '12345',
name: 'Hai Chau',
code: 12
},
{
_id: '123455',
name: 'Lien CHieu',
code: 13
},
{
_id: '1234567',
name: 'Cam Le',
code: 14
},
{
_id: '12345678',
name: 'Son Tra',
code: 15
}
]
How can i select User by both of two options (disctrict.name && index) like as district.name = 'Lien Chieu' && address.index > 1.
You can try this below query :
db.District.aggregate([
/** filter required doc from district Coll */
{ $match: { name: "Lien CHieu" } },
{
$lookup: {
from: "User",
let: { id: "$_id" },
pipeline: [
/** Basic filter to get matched doc from User Coll */
{ $match: { $expr: { $in: ["$$id", "$address.district_id"] } } },
/** check for criteria */
{
$addFields: {
mappingField: {
$map: {
input: "$address", as: "each", in: {
$and: [{ $gt: ["$$each.index", 1] }, { $eq: ["$$id", "$$each.district_id"] }]
}
}
}
}
},
/** filter required doc from above which matches our criteria & remove added field */
{ $match: { mappingField: true } }, { $project: { mappingField: 0 } }
],
as: "userdata"
}
}
])
Test : MongoDB-Playground

Query embedded document in mongoDB

I'm trying to query a Group document that has Users sub documents.
But I only want the subdocuments that belong to the user,
but I'm also getting data of other users.
Look at the query result, UserStatus field, only one of them belongs to the user.
The query result -
[
{
"_id": "5b1bcc12d5cdbf2cf78f2133",
"name": "First group ever",
"users": [
{
userId: 1,
"userStatus": "I"
},
{
userId: 2,
"userStatus": "I"
}
]
}
]
Group.js -
const GroupSchema = mongoose.Schema({
name: {
type: String,
required: true
},
users: [{
userId: {
type: mongoose.SchemaTypes.ObjectId,
ref: 'users',
required: true
},
userStatus: {
type: String,
required: true
}
}]
})
Query -
Group.find({
"users": {
$elemMatch: {
userId: req.params.id,
$or: [{
userStatus: "I"
}, {
userStatus: "A"
}]
}
}
}, "_id name users.userStatus",
function (err, groups) {
if (err)
res.send(err)
res.json(groups);
});

MongoDB $pull from array with filter

I have User collection:
[
{
_id: '5b3935c2d4850aa2d9f0ae25',
feedBucket: [
{
_id: '2a3535c2d4852ba2d9f0ae52',
createdAt: '2018-06-30 21:52:22.681'
},
{
_id: '9f342c2d4852ba2d9f0ae52',
createdAt: '2018-06-30 21:52:22.681'
}
]
},
{
_id: '3d2343c2d4850aa2d9f0ae33',
feedBucket: [
{
_id: '2a3535c2d4852ba2d9f0ae52',
createdAt: '2018-02-30 21:52:22.681'
},
{
_id: '9f342c2d4852ba2d9f0ae52',
createdAt: '2018-06-30 21:52:22.681'
}
]
}
]
And I am trying to pull document with id - '9f342c2d4852ba2d9f0ae52' from users feedBucket.
await User.updateMany(
{},
{ $pull: { feedBucket: { _id: '9f342c2d4852ba2d9f0ae52' } } },
{ multi: true }
)
but it doesn't work, result is { n: 2, nModified: 0, ok: 1 }
If your feedBucket._id is ObjectId then you need to $pull it by converting to mongoose ObjectId
const user = await User.update(
{ },
{ $pull: { feedBucket: { _id: mongoose.Types.ObjectId('5b07fa836569d356ba5bd2fa') } } },
{ multi: true }
)