Pull Document By ID from Triple Nested Array MongoDB - mongodb

I'd like to be able to pull a document by id from a triple nested array of documents. DB looks something like this:
[{
type: "Foods",
fruit: [{
name: "Apple",
kinds: [{
name: "Red Delicious"
details: [{
_id: ObjectId("123123123"),
colors: ["red", "yellow"]
}]
}]
}]
}]
I'd like to be able to pull the document with the _id: 123123123. I've tried many different ways, but it always says it matches, but won't modify the document.
I've tried:
db.stuff.update({}, {$pull: {fruits: {kinds: {details: {_id: "123123123"}}}}}),
db.stuff.update({}, {$pull: {"fruits.kinds.details' : {_id: "123123123"}}}),
db.stuff.update({}, {$pull: {"fruits.$[].kinds.$[].details' : {_id: "123123123"}}})
But everytime it matches, but won't delete the document.
Please help.

The last attempt is correct however you need to fix two things: fruit instead of fruit (according to your sample data) and types needs to match so you have to convert string to ObjectId
db.stuff.update({}, {$pull: {"fruit.$[].kinds.$[].details' : {_id: mongoose.Types.ObjectId("123123123")}}})

Related

Multilayered find and update mongodb and nodejs

Learning MongoDB so I hope that this is not a duplicate question.
So big picture. Users can add/remove items from their cart (which is an array).
The cart array holds objects who are structured as follows: {_id: 123r32, qty: 2}
The user document is structured as follows:
_id: 123432423,
username: johndoe,
email: johndoe#mail.com,
cart: [
{
_id: wefw3423,
qty: 100
}
]
So adding to the array is fine:
db.users.updateOne({_id: req.user.id}, {$push: {cart: {_id: req.body.id, qty: req.body.qty}}})
But when I push, I don't want to add a duplicate. I want to just adjust the qty (add/subtract) accordingly. If no instance of that _id exists, push.
Thank you for reading and your help! Should you need additional information, please ask I shall provide!.
EDIT:
Additional information. The request body (req.body) will contain only ONE item. So updateMany will not be required here.
db.users.updateOne({_id: req.user.id}, {$set: { "cart.$[element]": {_id:"wefw3423",qty:50}}, { arrayFilters: [ { element: _id:"wefw3423" } ]},{ upsert:true})
MongoDB reference :
https://docs.mongodb.com/manual/reference/operator/update/positional-filtered/#mongodb-update-up.---identifier--

Building mongo query

I have a model like this:
[{item: {
_id: 123,
field1: someValue,
price: {
[_id: 456,
field1: anotherValue,
type: []],
[_id: 789,
field1: anotherValue,
type: ['super']]
}
}]
I need to find an item by 3 parameters: item _id, price _id, and check if price type array is empty. And check it in one price field.
Model.findOneAndUpdate({_id: 123, "price._id": 456, "price.type": {size:0})
This query always returns item, cause search in different prices.
Model.findOneAndUpdate({_id: 123, price: {id: 456, type: {size:0})
This query returns error (cast array value or something like this).
tried to build query with $in, $and, but still getting an error
Use $elemMatch:
The $elemMatch operator matches documents that contain an array field
with at least one element that matches all the specified query
criteria.
db.inventory.find({
price: {
"$elemMatch": {
_id: 456,
type: {
$size: 0
}
}
}
})

MongoDB: Upsert document in array field

Suppose, I have the following database:
{
_id: 1,
name: 'Alice',
courses: [
{
_id: 'DB103',
credits: 6
},
{
_id: 'ML203',
credits: 4
}
]
},
{
_id: 2,
name: 'Bob',
courses: []
}
I now want to 'upsert' the document with the course id 'DB103' in both documents. Although the _id field should remain the same, the credits field value should change (i.e. to 4). In the first document, the respective field should be changed, in the second one, {_id: 'DB103', credits: 4} should be inserted into the courses array.
Is there any possibility in MongoDB to handle both cases?
Sure, I could search with $elemMatch in courses for 'DB103' and if I haven't found it, insert, otherwise update the value. But these are two steps and I would like to do both in just one.

How to update specified Document in MongoDB with Javascript

I have a document like this:
[ { _id: 55535305c6d17454276beba1,
name: 'Localhost',
tables: [{ chairs:[{
data:[{
}]
}]
}]
}
]
I want to update/insert new data in the data document.
You can do something along these lines for your example:
db.collectionName.update(
{_id: 55535305c6d17454276beba1},
{$set: {"tables.chairs.data" : [{somethingHere:1}] }}
);
You can update individual elements in the data array by using this syntax:
db.collectionName.update(
{_id: 55535305c6d17454276beba1},
{$set: {"tables.chairs.data.0" : {somethingHere:2} }}
);
This link provides some additional examples:
Updating Value of Array Element in MongoDB

MongoDB: aggregate $project add field with static value

Can I somehow add custom field with static (not computed) value?
I want to prepare objects before send and I need to remove some fields with internal information and add field with some entity ID.
For example I have collection "test" with objects like this
{_id: ObjectId(...), data: {...}}
And I need to convert it to
{data: {...}, entity_id: 54}
So how can I add entity_id: 54 without looping over result in my code?
db.test.aggregate({ $project: {_id: 0, data: 1, entity_id: ? } })
Thanks
Note that $literal was implemented in Mongo 2.6.
So now you can simply write:
db.test.aggregate(
{$project: {_id: 0, data: 1, entity_id: {$literal: 54}}})
See $literal.
edit as of 2.6 the $literal expression exists so you don't have to use the workaround now.
Original answer: I know this may sound really dumb, but you can use a "no-op" expression to "compute" what you need.
Example:
db.test.aggregate( { $project : {_id:0, data:1, entity_id: {$add: [54]} } } )
There was a proposed $literal operator for exactly this use case but it hasn't been implemented yet, you can vote for it here.