Add and update child arrays value in Mongo db - arrays

I want to add value in array of the following json structure in mongo db collection "Scdtls".
I need to add value only where "Type": "Fees" and "IsCurrentVersion": true.
{
"_id": ObjectId("60e71243b484cf3ec22a6845"),
"Item": "School",
"Text": "School Details",
"Types": [
{
"Type": "Library",
"Values": [
{
"IsCurrentVersion": false,
"KeyWords": [
{
"_id": ObjectId("611a4f113800d6af3fc4814f"),
"Value": "Physics"
}
]
}
]
},
{
"Type": "Fees",
"Values": [
{
"IsCurrentVersion": false,
"KeyWords": [
{
"_id": ObjectId("611a4f113800d6af3fc4814f"),
"Value": "Admission"
},
{
"_id": ObjectId("611a4f113800d6af3fc4814k"),
"Value": "Canteen"
}
]
},
{
"IsCurrentVersion": true,
"KeyWords": [
{
"_id": ObjectId("611a4f113800d6af3fc4814g"),
"Value": "Tution"
}
]
}
]
}
]
}
This is how I am trying
db.Scdtls.update({
"Item": "School",
"Types.Type": "Fees",
"Types.Values.IsCurrentVersion": true
},
{
"$push": {
"Types.1.Values.$[].KeyWords": {
"_id": ObjectId(),
"Value": "Sports"
}
}
})
But it is also adding "Value": "Sports" in "Type" : "Fees" where "IsCurrentVersion": false.
Not able to understand the reason.

If I understand correctly, you can do the update you want using "arrayFilters", like this:
db.Scdtls.update({
"Item": "School",
"Types.Type": "Fees",
"Types.Values.IsCurrentVersion": true
},
{
"$push": {
"Types.$[x].Values.$[y].KeyWords": {
"_id": ObjectId("deadbeafcafebabec0deface"),
"Value": "Sports"
}
}
},
{
"arrayFilters": [
{ "x.Type": "Fees" },
{ "y.IsCurrentVersion": true }
]
})
Try it on mongoplayground.net.

Related

MongoDB How to search in nested objects?

How i can search for the value "20044" in all fields "Barcode" and just in field "Barcode" in a nested object without specifying an absolute path e.g. "Item.Item.Item.Barcode" in MongoDB?
My current solutions:
Search in all text fields, not only in "Barcode" fields
find({$text: {$search: '20044'}})
Search in one specifying absolute path and not in all "Barcode" fields
find({'Item.Item.Item.Barcode': '20044'})
This is my databse object:
{
"_id": {
"$oid": "633d7cc238d7f8dafeace6f5"
},
"Number": "2",
"Item": [
{
"Type": "FrameElement",
"Item": [
{
"Type": "Frame",
"Barcode": "20011"
},
{
"Type": "Frame",
"Barcode": "20012"
},
{
"Type": "SashElement",
"Item": [
{
"Type": "Sash",
"Barcode": "20021"
},
{
"Type": "Sash",
"Barcode": "20022"
},
{
"Type": "GlassBarElement",
"Item": [
{
"Type": "GlassBar",
"Barcode": "20031"
},
{
"Type": "GlassBar",
"Barcode": "20032"
}
]
}
]
},
{
"Type": "Glass",
"Barcode": "20016"
},
{
"Type": "GlassBarElement",
"Item": [
{
"Type": "GlassBar",
"Barcode": "20043"
},
{
"Type": "GlassBar",
"Barcode": "20044"
}
]
}
]
}
]
}

How to use projection for nested value in mongod

How to use projection to view only the below part from all docs of the collection?
Conditions:
I need to fetch only for "type": "DEBIT" and below 2 lines, NOT all other keys in the same type.
I dont want to view other types like Account, Deposit.
{
"key": "Call",
"enabled": true,
}
Sample Docs which i have in the below structure.
{
"_id": "1",
"menu": [
{
"type": "ACCOUNT",
"scope": "ACCOUNT",
"items": [
{
"key": "Call",
"enabled": true,
},
{
"key": "Work",
"enabled": true,
}
]
},
{
"type": "DEPOSIT",
"scope": "DEPOSIT",
"items": [
{
"key": "Call",
"enabled": true,
},
{
"key": "Work",
"enabled": true,
}
]
},
{
"type": "DEBIT",
"scope": "DEBIT",
"items": [
{
"key": "Call",
"enabled": true,
},
{
"key": "Work",
"enabled": true,
}
]
},
]
}
first, you need to $unwind the menu
then $match type debit
and filter array items and then group to create the final result
db.collection.aggregate([
{
"$unwind": "$menu"
},
{
$match: {
"menu.type": "DEBIT"
}
},
{
"$project": {
_id: 1,
"menu.items": {
"$filter": {
"input": "$menu.items",
"as": "s",
"cond": {
$and: [
{
$eq: [
"$$s.enabled",
true
]
},
{
$eq: [
"$$s.key",
"Call"
]
}
]
}
}
}
}
},
{
"$group": {
"_id": "$_id",
"menu": {
"$push": "$menu"
}
}
}
])
https://mongoplayground.net/p/kRChgF9rLsI
use $filter
db.collection.aggregate([
{
"$match": {
"menu.type": "DEBIT"
}
},
{
"$set": {
"menu": {
"$filter": {
"input": "$menu",
"as": "m",
"cond": {
$eq: [
"$$m.type",
"DEBIT"
]
}
}
}
}
}
])
mongoplayground

wanted to identify nested array value and replace it

{
"_id": "100",
"menu": [
{
"type": "1",
"isenabled": true,
"items": [
{
"key": "activity",
"enabled": true,
"criteria": [
{
"key": "account",
"value": [
"active"
],
"isExclude": false
}
],
"eligible": [
"QA",
"DE"
],
"isItem": false
}
]
}
}
I have below types of docs in a collection.
Here i wanted to identify the value like active and replace that to "inactive" in all docs.
How can we do that in multiple docs at a time.
"value": [
"active"
]
I tried few things but its not working as expected.
db.getCollection('test').update({},
{
$Set: {"menu.$[m].items.$[i].criteria.$[c].value":["inactive"]}
},
{
arrayFilters:
[
{
"m.type":"1"
},
{
"i.key": "activity"
},
{
"c.key": "account"
}
],
multi: true
})
$set not $Set
db.collection.update({},
{
$set: {
"menu.$[m].items.$[i].criteria.$[c].value": [
"inactive"
]
}
},
{
arrayFilters: [
{
"m.type": "1"
},
{
"i.key": "activity"
},
{
"c.key": "account"
}
],
multi: true
})
mongoplayground

Need a match an array value in mongodb and append into that

{
"_id": "100",
"menu": [
{
"type": "1",
"isenabled": true,
"items": [
{
"key": "activity",
"enabled": true,
"criteria": [
{
"key": "account",
"value": [
"active"
],
"isExclude": false
}
],
"eligible": [
"QA",
"DE"
],
"isItem": false
}
]
}
}
I have below types of docs in a collection.
Here i wanted to identify the eligible like wherever its ONLY "QA","DE", we need to add few extra value.
How can we do that in multiple docs at a time.
"eligible": [
"QA",
"DE"
]
use $push
db.collection.update({},
{
$push: {
"menu.$[m].items.$[i].eligible": "US"
}
},
{
arrayFilters: [
{
"m.type": "1"
},
{
"i.eligible": [
"QA",
"DE"
]
}
],
multi: true
})
mongoplayground

how to apply if-else for a complex JSON array

here is the Sample Json:-
[
{
"index": 0,
"object": {
"uri": "entities/oAFpSUX",
"type": "configuration/entityTypes/Pet",
"createdBy": "abc#xyz.com",
"createdTime": 1531431176965,
"updatedBy": "abc#xyz.com",
"updatedTime": 1531431177691,
"attributes": {
"Weight": [
{
"label": "5 lbs",
"value": {
"PetWeightMeasurement": [
{
"ov": true,
"value": "5",
}
],
"PetWeightUOM": [
{
"ov": true,
"value": "lbs",
"lookupCode": "lbs",
}
]
},
"ov": true,
"uri": "entities/oAFpSUX/attributes/Weight/1AeFvD8Kj"
}
],
"Identifiers": [
{
"label": "5155445576",
"value": {
"Type": [
{
"ov": false,
"value": "CRMO_Pet_Id",
}
],
"ID": [
{
"ov": true,
"value": "5155445576",
}
]
},
"ov": true,
"uri": "entities/oAFpSUX/attributes/Identifiers/1AeFvCrHh"
}
],
"Vaccination": [
{
"label": "Bordatella - 2018-10-26",
"value": {
"Type": [
{
"type": "configuration/entityTypes/Pet/attributes/Vaccination/attributes/Type",
"ov": true,
"value": "Bordatella",
"lookupCode": "4",
"lookupRawValue": "Bordatella",
"lookupAttributes": [
{
"name": "Sort Order",
"value": "3"
}
],
"uri": "entities/oAFpSUX/attributes/Vaccination/1AeFv9yGr/Type/1AeFvA2X7"
}
],
"ExpirationDate": [
{
"type": "configuration/entityTypes/Pet/attributes/Vaccination/attributes/ExpirationDate",
"ov": true,
"value": "2018-10-26",
"uri": "entities/oAFpSUX/attributes/Vaccination/1AeFv9yGr/ExpirationDate/1AeFvA6nN"
}
]
},
"ov": true,
"uri": "entities/oAFpSUX/attributes/Vaccination/1AeFv9yGr"
},
{
"label": "Distemper - 2018-10-25",
"value": {
"Type": [
{
"type": "configuration/entityTypes/Pet/attributes/Vaccination/attributes/Type",
"ov": true,
"value": "Distemper",
"lookupAttributes": [
{
"name": "Sort Order",
"value": "4"
}
],
"uri": "entities/oAFpSUX/attributes/Vaccination/1AeFv9YhJ/Type/1AeFv9cxZ"
}
],....
My question: I was able to get the value of "$..Vaccination..value.Type..value" as "Bordatella" so that works fine. However what I now want is that if the value is 'Bordatella' then I want to extract the "value" under "ExpirationDate". Can someone please help me how I can extract that "value" under "ExpirationDate" ? I am not sure if I need to do that with some custom Groovy code of using jmeter's if controller. Any help would be greatly appreciated!
Thanks.
There are several ways to run jq queries from within Java - e.g.
https://github.com/eiiches/jackson-jq
https://github.com/arakelian/java-jq (available from Maven Central)
Java Native Access wrapper https://github.com/bskaggs/jjq . Supported platform is Linux only.
Assuming the sample input has been revised in the obvious way to make it valid JSON, the following jq filter will produce the output as shown:
.[].object.attributes.Vaccination[].value
| select(.Type[].value == "Bordatella")
| .ExpirationDate[].value
Output:
"2018-10-26"
Alternative
Here's a jq filter that is agnostic about the relative location of the "Vaccination" object:
..
| objects
| select(has("Vaccination"))
| .Vaccination[].value?
| select(.Type[].value == "Bordatella")
| .ExpirationDate[].value
Given the following JSON response:
[
{
"index": 0,
"object": {
"uri": "entities/oAFpSUX",
"type": "configuration/entityTypes/Pet",
"createdBy": "a...#xyz.com",
"createdTime": 1531431176965,
"updatedBy": "a...#xyz.com",
"updatedTime": 1531431177691,
"attributes": {
"Weight": [
{
"label": "5 lbs",
"value": {
"PetWeightMeasurement": [
{
"ov": true,
"value": "5"
}
],
"PetWeightUOM": [
{
"ov": true,
"value": "lbs",
"lookupCode": "lbs"
}
]
},
"ov": true,
"uri": "entities/oAFpSUX/attributes/Weight/1AeFvD8Kj"
}
],
"Identifiers": [
{
"label": "5155445576",
"value": {
"Type": [
{
"ov": false,
"value": "CRMO_Pet_Id"
}
],
"ID": [
{
"ov": true,
"value": "5155445576"
}
]
},
"ov": true,
"uri": "entities/oAFpSUX/attributes/Identifiers/1AeFvCrHh"
}
],
"Vaccination": [
{
"label": "Bordatella - 2018-10-26",
"value": {
"Type": [
{
"type": "configuration/entityTypes/Pet/attributes/Vaccination/attributes/Type",
"ov": true,
"value": "Bordatella",
"lookupCode": "4",
"lookupRawValue": "Bordatella",
"lookupAttributes": [
{
"name": "Sort Order",
"value": "3"
}
],
"uri": "entities/oAFpSUX/attributes/Vaccination/1AeFv9yGr/Type/1AeFvA2X7"
}
],
"ExpirationDate": [
{
"type": "configuration/entityTypes/Pet/attributes/Vaccination/attributes/ExpirationDate",
"ov": true,
"value": "2018-10-26",
"uri": "entities/oAFpSUX/attributes/Vaccination/1AeFv9yGr/ExpirationDate/1AeFvA6nN"
}
]
},
"ov": true,
"uri": "entities/oAFpSUX/attributes/Vaccination/1AeFv9yGr"
},
{
"label": "Distemper - 2018-10-25",
"value": {
"Type": [
{
"type": "configuration/entityTypes/Pet/attributes/Vaccination/attributes/Type",
"ov": true,
"value": "Distemper",
"lookupAttributes": [
{
"name": "Sort Order",
"value": "4"
}
],
"uri": "entities/oAFpSUX/attributes/Vaccination/1AeFv9YhJ/Type/1AeFv9cxZ"
}
]
}
}
]
}
}
}
]
Add JSR223 PostProcessor as a child of the request which returns the above response
Put the following code into "Script" area:
new groovy.json.JsonSlurper().parse(prev.getResponseData()).get(0).get('object').get('attributes').get('Vaccination').each { vaccination ->
if (vaccination.get('value').get('Type').get(0).get('value').equals('Bordatella')) {
def expirationDate = vaccination.get('value').get('ExpirationDate').get(0).get('value')
log.info('ExpirationDate: ' + expirationDate)
vars.put('ExpirationDate', expirationDate)
}
}
If everything goes well (your JSON response matches the Groovy code) the ExpirationDate will be:
printed to jmeter.log file
stored as ${ExpirationDate} JMeter Variable
Demo:
More information:
Groovy: Parsing and producing JSON
Apache Groovy - Why and How You Should Use It

Resources