Jolt for complex JSON transform - jolt

Extracting values from first array element and second element and joining both.
Input String:
[
{
"creationDate": "2020-04-01T14:14:32.685+0000",
"factValues": [
{
"Factname": "Medicine",
"factvalue": "1234556",
"sourcePguid": "1"
},
{
"Factname": "Journal",
"factvalue": "123455",
"sourcePguid": "1"
}
]
},
{
"creationDate": "2020-04-01T14:14:32.685+0000",
"factValues": [
{
"Factname": "chemical",
"factvalue": "123455567",
"sourcePguid": "2"
},
{
"Factname": "Rubber",
"factvalue": "123455435",
"sourcePguid": "3"
}
]
}
]
Output excepted:
{
{
"sourcePguid" : "1",
"Medicine":"1234556",
"Journal":"123455"
}, {
"sourcePguid" : "2",
"chemical":"123455567",
"Rubber":"123455435"
}
}
Kindly help me to achieve the expected output.json in spec.json. The spec is not transforming as expected output. I want learn how to use attributes inside the string parser.It would be great.

Hope this might help,
[
{
"operation": "shift",
"spec": {
"*": {
"factValues": {
"*": {
"sourcePguid": "&3.sourcePguid",
"#(0,factvalue)": "&3.#Factname"
}
}
}
}
}, {
"operation": "modify-overwrite-beta",
"spec": {
"*": {
"sourcePguid": "=firstElement(#(1,sourcePguid))"
}
}
}
]

Yet another answer using JSONata
For java: https://github.com/IBM/JSONata4Java
$.factValues{
sourcePguid: {
"sourcePguid": $distinct(sourcePguid),
Factname:factvalue
}
} ~> $each(function($v){$v})

Related

mongodb: updating an object inside array using forEach

I'm having a collection called vehicles whose structure is given below.
[
{
"vehicleType":"car",
"parts":[
{
"partName":"engine",
"buyingPrice":145.00,
"sellingPrice":200.00
},
{
"partName":"brake",
"buyingPrice":50.00,
"sellingPrice":70.00
},
{
"partName":"wheel",
"buyingPrice":70.00,
"sellingPrice":75.00
}
]
},
{
"vehicleType":"bike",
"parts":[
{
"partName":"engine",
"buyingPrice":1450.00,
"sellingPrice":2000.00
},
{
"partName":"brake",
"buyingPrice":507.00,
"sellingPrice":170.00
},
{
"partName":"wheel",
"buyingPrice":70.00,
"sellingPrice":75.00
}
]
},
{
"vehicleType":"car",
"parts":[
{
"partName":"engine",
"buyingPrice":1450.00,
"sellingPrice":2000.00
},
{
"partName":"brake",
"buyingPrice":50.00,
"sellingPrice":170.00
},
{
"partName":"wheel",
"buyingPrice":700.00,
"sellingPrice":750.00
}
]
}
]
I want to update the sellingPrice as 500.00 if the partName is brake and sellingPrice is <= 170.00. I excuted the below query, but it is updating the value only for the 1st object.
db.getCollection("vehicles").find({})
.forEach(function(v){
v.parts.forEach(function(p){
if(p.partName=="brake" && p.sellingPrice<=170.00){
p.sellingPrice=500.00;
print(v);
}
})
})
Below is the output of above query
[
{
"vehicleType":"bike",
"parts":[
{
"partName":"engine",
"buyingPrice":1450.00,
"sellingPrice":2000.00
},
{
"partName":"brake",
"buyingPrice":507.00,
"sellingPrice":500.00
},
{
"partName":"wheel",
"buyingPrice":70.00,
"sellingPrice":75.00
}
]
},
{
"vehicleType":"car",
"parts":[
{
"partName":"engine",
"buyingPrice":1450.00,
"sellingPrice":2000.00
},
{
"partName":"brake",
"buyingPrice":50.00,
"sellingPrice":170.00
},
{
"partName":"wheel",
"buyingPrice":700.00,
"sellingPrice":750.00
}
]
}
]
Don't know what went wrong. Any help is appreciated. Thanks in advance.
I think that the easiest way to do that is with the following query using the positional operator $
db.getCollection('vehicles').updateMany({
"parts.partName": "brake",
"parts.sellingPrice": {
$lte: 170.00
}
},
{
"$set": {
"parts.$.sellingPrice": 500
}
})
In case you can use mongodb cursor methods like forEach try something like this.

JSON array transform with JOLT

I receive following JSON from some REST API:
{
"operation_id" : [ 1405494, 1409934, 1420753 ],
"operation_status" : "success"
}
I want to split operation_id from array to get 1 by 1 value and create new JSON which should look like:
{
"operationsStatus": [
{
"operation_id": 1405494,
"operation_status": "success"
},
{
"operation_id": 1409934,
"operation_status": "success"
},
{
"operation_id": 1420753,
"operation_status": "success"
}
]
}
Can I do it with JOLT spec?
You can walk through the operation_id array by using a shift transformation such as
[
{
"operation": "shift",
"spec": {
"*": {
"operation_id": {
"*": {
"#": "operationsStatus[&1].&2",
"#(2,operation_status)": "operationsStatus[&1].operation_status"
}
}
}
}
}
]
the Result of the demo on https://jolt-demo.appspot.com/

Split array inside JSON with JOLT

I have a JSON look like:
[
{
"mainId": 12854,
"subIds": [
25,
26,
27
]
}
]
I want to split values inside subIds to create diffrent rows.
Can I get expected result with JOLT?
[
{
"mainId": 12854,
"subId": 25
},
{
"mainId": 12854,
"subId": 26
},
{
"mainId": 12854,
"subId": 27
}
]
You can walk through the indexes of subIds array while grabbing the value of mainId by #(2,mainId) in order to going up the three two levels, and using [&1] as common factor to reach those indexes such as
[
{
"operation": "shift",
"spec": {
"*": {
"subIds": {
"*": {
"#": "[&1].subId",
"#(2,mainId)": "[&1].mainId"
}
}
}
}
}
]

MongoDb aggregation project onto collection

I've a problem with a huge MongoDb aggregation pipeline. I've many constraint and I've simplified the problem a lot. Hence, don't discuss the goal for this query.
I've a mongo aggregation that gives something similar to this:
[
{
"content": {
"processes": [
{
"id": "101a",
"title": "delivery"
},
{
"id": "101b",
"title": "feedback"
}
]
}
}
]
To this intermediate result I'm forced to apply a project operation in order to obtain something similar to this:
[
{
"results":
{
"titles": [
{
"id": "101a",
"value": "delivery"
},
{
"id": "101b",
"value": "feedback"
}
]
}
}
]
enter code here
But applying this projections:
"results.titles.id": "$content.processes.id",
"results.titles.value": "$content.processes.title"
I obtain this:
[
{
"results":
{
"titles": {
"id": ["101a", "101b"]
"value": ["delivery", "feedback"]
}
}
}
}
]
Collection are created but not in the proper position.
Is it possible to exploit some operator inside the project operation in order to tell mongo to create an array in a parent position?
Something like this:
"results.titles.$[x].value" : "$content.processes.value"
You can use the dot notation to project entire array:
db.col.aggregate([
{
$project: {
"results.titles": "$content.processes"
}
}
])
and if you need to rename title to value then you have to apply $map operator:
db.col.aggregate([
{
$project: {
"results.titles": {
$map: {
input: "$content.processes",
as: "process",
in: {
id: "$$process.id",
value: "$$process.title"
}
}
}
}
}
])

Date Filter on elastic search

I'm trying to create a Range Filter on elastic search using the following syntax:
{
"size": 100,
"filter": {
"and": {
"filters": [
{
"range": {
"listingDate": {
"gt": "15/07/2017 16:08:53"
}
}
}
]
}
}
}
The data format is:
"listingDate": "07/07/2015 09:30:00",
However regardless of the filter properties the same incorrect results are being returned by elastic search. I have tried adding the following format:
"format": "dd/MM/yyyy HH:mm:ss"
but I get the same incorrect results.
A fuller example is:
{
"size": 100,
"sort": [
{
"listingDate": {
"order": "asc"
}
}
],
"query": {
"bool": {
"must": [
{
"query_string": {
"query": "Event"
}
},
{
"range": {
"listingDate": {
"gte": "15/07/2015 16:08:53"
}
}
},
{
"range": {
"endDate": {
"gte": "15/07/2015 16:08:53"
}
}
}
]
}
},
"filter": {
"and": {
"filters": [
{
"terms": {
"departments": [
"2393"
]
}
}
]
}
}
}
In JSON documents, dates are represented as strings. Elasticsearch uses a set of preconfigured formats to recognize and parse these strings into a long value representing milliseconds-since-the-epoch in UTC. It might be possible that your date field might not be listed in the set of preconfigured ES date formats.
Formatted dates will be parsed using the format specified on the date field by default, but it can be overridden by passing the format parameter to the range query.
{
"range" : {
"listingDate" : {
"gte": "07/07/2015 09:30:00",
"format": "dd/MM/yyyy HH:mm:ss"
}
}
}
let suppose "arr" argument have a date range e.g. ["2019-07-10","2019-07-11"]
let start_date_query;
let range=[];
if ( arr.date_from ){
if(arr.date_from[1]){
range.push({
"range":{
"start_date":{ "gte":arr.date_from[0] }
}
});
range.push({
"range":{
"end_date":{ "lte": arr.date_from[1] }
}
});
start_date_query = {
"query": {
"constant_score": {
"filter": {
"bool": {
"must":range
}
}
}
};
}
}
}