I am trying to transform array value as string to my object using jolt. When I convert array value to String, I am not able to get the proper value in my object.
Input Json :
"id": [
"123",
"245"
],
"lastName": [
"john",
"Mary"
],
"firstName": [
"doe",
"Ann"
],
"subjects": [
[
"['Maths']",
"['Science']",
"['English']"
],
[
"['English']",
"['Accounts']",
"['Art']"
]
]
}
Jolt Spec:
[{
"operation": "shift",
"spec": {
"*": {
"*": {
"*": {
"$": "[&2].&3"
}
}
}
}
}]
Expected output :
[ {
"id" : "123",
"lastName" : "john",
"firstName" : "doe",
"subjects" : [ ["['Maths']","['Science']","['English']"] ]
}, {
"id" : "245",
"lastName" : "Mary",
"firstName" : "Ann",
"subjects" : [ ["['English']","['Accounts']","['Art']"] ]
} ]
Actual Output:
[ {
"id" : "123",
"lastName" : "john",
"firstName" : "doe",
"subjects" : [ "0", "1", "2" ]
}, {
"id" : "245",
"lastName" : "Mary",
"firstName" : "Ann",
"subjects" : [ "0", "1", "2" ]
} ]
Please help. Thanks in advance.
Check if this solves it. Think you were missing a level at the subjects array:
[{
"operation": "shift",
"spec": {
"*": {
"*": {
"*": {
"$": "[&2].&3"
}
}
},
"subjects": {
"*": {
"*": {
"*": {
"$": "[&3].&4"
}
}
}
}
}
}]
cheers
Related
I want to always replace
abcd with abcd.india
xyxvv with ind.hello
india.gateway.url/time/123/v1 with india.ios.gw.url/time/123/v2
'someText' with 'diffText'
presented in website under information array, without modifying prefix and suffix
Input :
{
"requestId": 1122344,
"Name": "testing",
"information": [
{
"website": "abcd/122/ty",
"city": "pune",
"pincode": false,
"client_name": 5
},
{
"website": "http://xyxvv/122/ty",
"city": "delhi",
"pincode": false,
"client_name": 5
},
{
"website": "http://someText",
"city": "delhi",
"pincode": false,
"client_name": 5
},
{
"website": "http://india.gateway.url/time/123/v1",
"city": "maharashtra",
"pincode": false,
"client_name": 6
}
],
"ReasonText": "something",
"Code": "ABCD"
}
Desired Output :
{
"requestId" : 1122344,
"Name" : "testing",
"information" : [ {
"website" : "abcd.india/122/ty",
"city" : "pune",
"pincode" : false,
"client_name" : 5
}, {
"website" : "http://ind.hello/122/ty",
"city" : "delhi",
"pincode" : false,
"client_name" : 5
}, {
"website" : "http://diffText",
"city" : "delhi",
"pincode" : false,
"client_name" : 5
},
{
"website" : "http://india.ios.gw.url/time/123/v2",
"city" : "delhi",
"pincode" : false,
"client_name" : 6
} ],
"ReasonText" : "something",
"Code" : "ABCD"
}
You can consecutively use split, join and concat functions to split the string, and then conditionally convert substrings and concatenate back all the pieces such as
[
{
"operation": "modify-overwrite-beta",
"spec": {
"information": {
"*": {
"ht": "=split('://',#(1,website))",
"ws": "=split('/',#(1,ht[1]))",
"last_ws": "=lastElement(#(1,ws))",
"size_ws": "=size(#(1,ws))"
}
}
}
},
{
"operation": "shift",
"spec": {
"*": "&",
"information": {
"*": {
"ws": {
"0": { // for the first omponent of the array composed splitting the sting by / characters
"abcd": {
"#abcd.india": "&5[&4].ws"
},
"xyxvv": {
"#ind.hello": "&5[&4].ws"
},
"india.gateway.url": {
"#india.ios.gw.hello": "&5[&4].ws"
}
},
"*": {
"v1": {
"#(3,last_ws)": {//whenever match occurs with v1, set it to v2(occurence assumed only at this leaf level)
"#v2": "&6[&5].ws"
}
},
"*": {
"#ind.hello": "&5[&4].ws"
}
}
},
"*": "&2[&1].&"
}
}
}
}
,
{
"operation": "modify-overwrite-beta",
"spec": {
"information": {
"*": {
"ws": "=join('/',#(1,ws))",
"website": "=concat(#(1,ht[0]),'://',#(1,ws))"
}
}
}
},
{
"operation": "remove",
"spec": {
"information": {
"*": {
"ht": "",
"ws": "",
"*ws": ""
}
}
}
}
]
Here i wanted to replace the value of country to something else wherever it presents like "India".
I have multiple docs with same structure and would like update all at once. It should not affect other keys and just wanted to update the country.
Tried with Set operator and not getting it correctly.
{
"_id" : "1",
"teams" :
[
{
"type" : "local",
"isEnabled" : "true",
"Country":"India"
"names" :
[
{ "name": "kumar","Nationality":"indian","BirthPlace":"Goa","Age":"U25" },
{ "name": "kannan","Nationality":"indian","BirthPlace":"Kerala","Age":"U25"}
]
},
{
"type" : "national",
"isEnabled" : "true",
"Country":"India"
"names" :
[
{ "name": "kumar","Nationality":"indian","BirthPlace":"Goa","Age":"U25" },
{ "name": "kannan","Nationality":"indian","BirthPlace":"Kerala","Age":"U25"}
]
},
{
"type" : "international",
"isEnabled" : "true",
"Country":"England"
"names" :
[
{ "name": "kumar","Nationality":"indian","BirthPlace":"Goa","Age":"U25" },
{ "name": "kannan","Nationality":"indian","BirthPlace":"Kerala","Age":"U25"}
]
},
{
"type" : "national",
"isEnabled" : "true",
"Country":"India"
"names" :
[
{ "name": "kumar","Nationality":"indian","BirthPlace":"Goa","Age":"U25" },
{ "name": "kannan","Nationality":"indian","BirthPlace":"Kerala","Age":"U25"}
]
},
{
"type" : "international",
"isEnabled" : "true",
"Country":"Newzealand"
"names" :
[
{ "name": "kumar","Nationality":"indian","BirthPlace":"Goa","Age":"U25" },
{ "name": "kannan","Nationality":"indian","BirthPlace":"Kerala","Age":"U25"}
]
}
]
}
Try this one:
db.collection.updateMany(
{},
{ $set: { "teams.$[element].Country": "Republic of India" } },
{ arrayFilters: [{ "element.Country": "India" }] }
);
Try this one:
db.collection.updateMany({},
{
$set: {
"teams.$[].Country": "India"
}
})
{
"_id" : "1",
"teams" :
[
{
"type" : "local",
"isEnabled" : "true",
"names" :
[
{ "name": "kumar","Nationality":"indian","BirthPlace":"Goa","Age":"U25" },
{ "name": "kannan","Nationality":"indian","BirthPlace":"Kerala","Age":"U25"}
]
},
{
"type" : "national",
"isEnabled" : "true",
"names" :
[
{ "name": "kumar","Nationality":"indian","BirthPlace":"Goa","Age":"U25" },
{ "name": "kannan","Nationality":"indian","BirthPlace":"Kerala","Age":"U25"}
]
},
{
"type" : "international",
"isEnabled" : "true",
"names" :
[
{ "name": "kumar","Nationality":"indian","BirthPlace":"Goa","Age":"U25" },
{ "name": "kannan","Nationality":"indian","BirthPlace":"Kerala","Age":"U25"}
]
},
]
}
I have multiple docs in the same format in a mongodb collection. I wanted to append the below lines into names array also only for "type: local" in each docs of the collections. I tried $push and its appending in all teams array as i am finding difficulty to add this condition only for "type":"local"
{
"name":"jack","Nationality":"indian","BirthPlace":" "Karnataka","Age":"U25"
}
You can use positional operator : $[]
db.collection.update({
"teams.type": "local"
},
{
$push: {
"teams.$[element].names": {
"name": "jack",
"Nationality": "indian",
"BirthPlace": "Karnataka",
"Age": "U25"
}
}
},
{
arrayFilters: [
{
"element.type": "local"
}
],
multi: true
})
Try it here
I got question might be many of you can help me.
so I have data on mongodb.
first data
{
"name" : 'david'
contacts : [
{
"name" : 'john',
"phone" : '123456'
},
{
"name" : 'george',
"phone" : '0987654'
}
]
}
second data
{
"name" : 'anita',
"contacts" : [
{
"name" : 'harry',
"phone" : '123456'
},
{
"name" : 'kurita',
"phone" : '323434'
}
]
}
the problem is,
can I query to find data that have duplicate contacts.phone.
so the result whill show like this.
{
"name" : 'david',
"contacts" : [
{
"name" : 'john',
"phone" : '123456'
}
]
}
{
"name" : 'anita',
"contacts" : [
{
"name" : 'harry',
"phone" : '123456'
}
]
}
data john and anita will show because they have similar data on contacts.phone
sorry for my english btw,
I hope you all understand what I mean.
thank you so much
There are a few steps involved to get the results you need.
We are going to write an aggregate pipeline to get the work done.
First you need to unwind your array values with the following:
{
$unwind: "$contacts"
}
Doc: https://docs.mongodb.com/manual/reference/operator/aggregation/unwind/
This would result into:
[
{
"_id": ObjectId("5a934e000102030405000000"),
"contacts": {
"name": "john",
"phone": "123456"
},
"name": "david"
},
{
"_id": ObjectId("5a934e000102030405000000"),
"contacts": {
"name": "george",
"phone": "0987654"
},
"name": "david"
},
{
"_id": ObjectId("5a934e000102030405000001"),
"contacts": {
"name": "harry",
"phone": "123456"
},
"name": "anita"
},
{
"_id": ObjectId("5a934e000102030405000001"),
"contacts": {
"name": "kurita",
"phone": "323434"
},
"name": "anita"
}
]
This would be much easier for us to group by field.
Doc: https://docs.mongodb.com/manual/reference/operator/aggregation/group/
{
$group: {
_id: {
phone: "$contacts.phone"
},
name: {
$addToSet: "$name"
},
contacts: {
$addToSet: "$contacts.name"
},
count: {
$sum: 1
}
}
}
That gives the following output:
[
{
"_id": {
"phone": "323434"
},
"contacts": [
"kurita"
],
"count": 1,
"name": [
"anita"
]
},
{
"_id": {
"phone": "123456"
},
"contacts": [
"john",
"harry"
],
"count": 2,
"name": [
"david",
"anita"
]
},
{
"_id": {
"phone": "0987654"
},
"contacts": [
"george"
],
"count": 1,
"name": [
"david"
]
}
]
Based on the output we need to match the count greater then 1 like:
Doc: https://docs.mongodb.com/manual/reference/operator/aggregation/match/
{
$match: {
count: {
"$gt": 1
}
}
}
Result is:
[
{
"_id": {
"phone": "123456"
},
"contacts": [
"john",
"harry"
],
"count": 2,
"name": [
"david",
"anita"
]
}
]
The query would look like:
Doc: https://docs.mongodb.com/manual/reference/operator/aggregation-pipeline/
db.collection.aggregate([
{
$unwind: "$contacts"
},
{
$group: {
_id: {
phone: "$contacts.phone"
},
name: {
$addToSet: "$name"
},
contacts: {
$addToSet: "$contacts.name"
},
count: {
$sum: 1
}
}
},
{
$match: {
count: {
"$gt": 1
}
}
}
])
MongoPlayground: https://mongoplayground.net/p/qSvhcYyAcQO
I hope this gives you a small idea what is possible with the aggregation pipeline.
Update / fix
According to your requirements you wish to have 2 objects foreach name that has duplicate contacts then you could use unwind again after the match.
[
{
"_id": {
"phone": "123456"
},
"contacts": [
"harry",
"john"
],
"count": 2,
"name": "david"
},
{
"_id": {
"phone": "123456"
},
"contacts": [
"harry",
"john"
],
"count": 2,
"name": "anita"
}
]
Cheers, Kevin
Can Jolt flatten an array of objects which contain array? For example, is there a way to write Jolt transformation specs for the following input and output?
Jolt https://github.com/bazaarvoice/jolt
Input:
[
{"Id": "111", ["mobile": "1111", "home": "1112"]},
{"Id": "222", ["mobile": "2221"]}
]
Output:
[
{"Id": "111", "mobile": "1111"},
{"Id": "111", "home": "1112"},
{"Id": "222", "mobile": "2221"}
]
I didn't find a way to represent the output array indexes.
assuming input is fixed as
[
{
"Id": "111",
"Val": [
{
"mobile": "1111"
},
{
"home": "1112"
}
]
},
{
"Id": "222",
"Val": [
{
"mobile": "2221"
}
]
}
]
then applying the following transformation
[
{
"operation": "shift",
"spec": {
"*": {
"Id": null,
"Val": {
"*": {
"#": "[&3].[&0]",
"#(2,Id)": "[&3].[&0].id"
}
}
}
}
},
{
"operation": "shift",
"spec": {
"*": {
"*": "[]"
}
}
}
]
reach the expected output:
[ {
"mobile" : "1111",
"id" : "111"
}, {
"home" : "1112",
"id" : "111"
}, {
"mobile" : "2221",
"id" : "222"
} ]