Hello folks struggling with this updatation
Any one can please help out here
"sheet_types": [
{
"areas": [
"FRONT",
"SIDE",
"UPPER"
]
}
]
}
I need to update the value of UPPER to TOP here
I have tried this query
db.company_settings.updateOne(
{"sheet_types.areas": "UPPER" },
{ $set: { "sheet_types.$.areas" : "TOP" } })
But the result i getting is
{
"sheet_types": [
{
"areas": [
"TOP"
]
}
]
}
Using "arrayFilters" seems to fit best for this use case:
db.collection.update({},
{
"$set": {
"sheet_types.$[].areas.$[filter]": "TOP"
}
},
{
"arrayFilters": [
{
"filter": "UPPER"
}
]
})
Explained:
Add arrayFIlter with one filter element equal to the value that you need to replace , use this filter to replace the value in the update statement. The advantage of this option is that it will replace all matching values that match the filter conditions in the document.
playground
Related
My question is a combination of:
This question: Removing the array element in mongoDB based on the position of element
And this question: mongodb set object where key value dynamically changes
I know you can define the field (array) dynamically like this:
{ [arrayName]: { <condition> } }
But, I then want to remove a certain element in a dynamically defined array by specifying the position (which is also defined dynamically). In other words, the function that processes this query is coming in which two parameters: the array's name and the index of the element to remove.
The options given by the selected answer were the following:
Option 1, does not work (in general), adapted to my case this looks like:
{ $pull : { [arrayName] : { $gt: index-1, $lt: index+1 } } }
Option 2, I cannot use dynamically defined values in field selectors with quotation marks (as far as I am aware):
{ $pull : "[arrayName].[index]" }
or
{ $pull : "[arrayName].$": index }
Option 3, is different method but can't use it for the same reason:
{ $unset: { "[arrayName].[index]": 1 } } // Won't work
{ $pull: { [arrayName]: null } } // Would probably work
The only workarounds I can think of right now involve significantly changing the design which would be a shame. Any help is appreciated!
PS: I'm using mongoose as a driver on the latest version as of today (v6.3.5) and MongoDB version 5.0.8
On Mongo version 4.2+ You can use pipelined updates to achieve this, you can get it done in multiple ways, here is what I consider the easiest two ways:
using $slice and $concatArrays to remove a certain element:
db.collection.update({},
[
{
$set: {
[arrayName]: {
$concatArrays: [
{
$slice: [
`$${arrayName}`,
index,
]
},
{
$slice: [
`$${arrayName}`,
index + 1,
{
$size: `$${arrayName}`
}
]
}
]
}
}
}
])
Mongo Playground
using $filter and $zip to filter out based on index:
db.collection.updateOne(
{},
[
{
"$set": {
[arrayName]: {
$map: {
input: {
$filter: {
input: {
$zip: {
inputs: [
{
$range: [
0,
{
$size: `$${arrayName}`
}
]
},
`$${arrayName}`
]
}
},
cond: {
$ne: [
{
"$arrayElemAt": [
"$$this",
0
]
},
index
]
}
}
},
in: {
$arrayElemAt: [
"$$this",
1
]
}
}
}
}
}
])
Alternatively you can just prepare
I have a database in MongoDB where there are entries with the following structure image
I am using a script in Python that I use to retrive information from this strucutre and then saves it to a csv.
The end goal is to remove ONLY SOME parts of the parameters structure. For instance, I want to keep parameters[0].values and parameters[1].values but not parameters[2:5].values
I am not experienced in this but the command I am using is the following
{"$unset":"exercises.parameters.values"] }
but this will remove all values from all the objects inside parameters. Since the variable has the same name amongst the objects I can't find a way to specify which ones I want.
I have also tried indexing like so
{"$unset":"exercises.parameters[2].values"] }
but that doesn't seem to work...
Help is much appreciated!
update
db.collection.update({
"_id": 1
},
{
"$unset": {
"exercises.$[].parameters.2.values": "",
"exercises.$[].parameters.3.values": "",
"exercises.$[].parameters.4.values": "",
"exercises.$[].parameters.5.values": ""
}
},
{
"multi": true
})
mongoplayground
aggregate
db.collection.aggregate([
{
$set: {
"exercises": {
"$map": {
"input": "$exercises",
"as": "item",
"in": {
"$mergeObjects": [
"$$item",
{
parameters: {
$slice: [ "$$item.parameters", 2 ]
}
}
]
}
}
}
}
}
])
mongoplayground
I am trying to find if any documents present and size more than one for a list which is inside two other lists in Mongo.
this is how my collection looks like:
{
"value": {
"items": [
{
"docs": [
{
"numbers": [
1,
2
]
},
{
"numbers": [
1
]
}
]
}
]
}
}
I tried to use this query and it did not work:
db.getCollection('MyCollection').find({"value.items.docs.numbers":{ $exists: true, $gt: {$size: 1} }})
What should be the ideal query to search if more than one item present inside list of list.
You are checking condition in nested array, for that nested $elemMatch condition will help to check conditions
$size allow only number as input so $not will help in negative condition
$ne to check array size should not [] empty
db.getCollection('MyCollection').find({
"value.items": {
$elemMatch: {
docs: {
$elemMatch: {
numbers: {
$exists: true,
$ne: [],
$not: {
$size: 1
}
}
}
}
}
}
})
Playground
In MongoDB, I have a movie collection that has an array of languages , e.g.
languages: [0:USA, 1: German, 2: French, ...etc]
The array values are not in any particular order.
How can I now update an array value based on some specific value? Let's say I want to update all "French" and replace it with "Francais" for the entire collection. How can I do that?
Use the positional $ operator which identifies the element in the languages array to update without explicitly specifying its position in the array i.e. instead of knowing the position in advance and updating the element as:
db.movies.updateMany(
{ "languages": "French" },
{ "$set": { "languages.2": "Francais" } }
)
you can just use the $ operator as:
db.movies.updateMany(
{ "languages": "French" },
{ "$set": { "languages.$": "Francais" } }
)
Alternatively using the aggregation pipeline for update operations:
db.movies.updateMany(
{ "languages": "French" },
[
{ "$set": {
"languages": {
"$map": {
"input": "$languages",
"in": {
"$cond": [
{ "$eq": ["$$this", "French"] },
"Francais",
"$$this"
]
}
}
}
} }
]
)
In case you have duplicate entries in your array like this:
"languages" : [
"USA",
"German",
"French",
"French"
]
You can use the following syntax to replace all occurrences starting with MongoDB v3.5.12 (documentation)
db.movies.updateMany(
{ "languages": "French" },
{ "$set": { "languages.$[filter]": "Francais" } },
{ "arrayFilters": [ { "filter": "French" } ] }
)
Strictly speaking, the { "languages": "French" } filter is not needed. It will, however, speed up things by leveraging an index on "languages" in case there is one. If that's not needed/wanted, passing a simple {} value as the first parameter works as well.
I have a document structure like
{
"_id" : ObjectId("52263922f5ebf05115bf550e"),
"Fields" : [
{
"Field" : "Lot No",
"Rules" : [ ]
},
{
"Field" : "RMA No",
"Rules" : [ ]
}
]
}
I have tried to update by using the following code to push into the Rules Array which will hold objects.
db.test.update({
"Fields.Field":{$in:["Lot No"]}
}, {
$addToSet: {
"Fields.Field.$.Rules": {
"item_name": "my_item_two",
"price": 1
}
}
}, false, true);
But I get the following error:
can't append to array using string field name [Field]
How do I do the update?
You gone too deep with that wildcard $. You match for an item in the Fields array, so you get a access on that, with: Fields.$. This expression returns the first match in your Fields array, so you reach its fields by Fields.$.Field or Fields.$.Result.
Now, lets update the update:
db.test.update({
"Fields.Field": "Lot No"
}, {
$addToSet: {
"Fields.$.Rules": {
'item_name': "my_item_two",
'price':1
}
}
}, false, true);
Please note that I've shortened the query as it is equal to your expression.