How to repeat multiple lists inside data weave in mule - json

The problem i am facing is with repeating multiple lists inside dataweave.
input of the dataweave --> coming in two flow varibles (as below),
var1: [{bkAuthorID=1, bkAuthorName=abc, bookCategory=horror}, {bkAuthorID=2, bkAuthorName=xyz, bookCategory=horror}, {bkAuthorID=1, bkAuthorName=abc, bookCategory=comedy}, {bkAuthorID=2, bkAuthorName=xyz, bookCategory=Fantacy}}]
var2: [{bkAuthorID=1, bkName=gjh, bkDescription=kjh},{bkAuthorID=1, bkName=sfs, bkDescription=kjh},{bkAuthorID=2, bkName=gjh, bkDescription=kjh},{bkAuthorID=2, bkName=gjh, bkDescription=kjh}]
output in dataweave --> desired json structue with three lists is like below.
{
"books": [
{
"bookAuthor": "abc",
"bookCategorys": [
{
"bookCategory": "horror",
"listOfBooks": [
{
"bookName": "xyz",
"bookDescription":"lmn"
},
{
"bookName": "xyz",
"bookDescription":"lmn"
}
]
},
{
"bookCategory": "comedy",
"listOfBooks": [
{
"bookName": "xyz",
"bookDescription":"lmn"
}
]
}
]
},
{
"bookAuthor": "xyz",
"bookCategorys": [
{
"bookCategory": "horror",
"listOfBooks": [
{
"bookName": "xyz",
"bookDescription":"lmn"
}
]
}
]
}
]
}
Can anyone help on this dataweave mapping for this requirement.
#Manik, can you please help me out.

I am able to establish relation between var1 and var2 using bkAuthorID.
But, there has to be one more relation to tell which book in var2 belongs to which category. Hence, in the below output, each category will have list of all the books written by that author. Anyways, all you need to do is just add one more filter condition in 'listOfBooks' line.
Dataweave code:
%dw 1.0
%output application/json
---
{
books:( flowVars.var1 groupBy $.bkAuthorName map using (authorId=$.bkAuthorID[0]) {
bookAuthor:$[0].bkAuthorName,
bookCategorys: $ groupBy $.bookCategory map {
bookCategory:$.bookCategory[0],
listOfBooks: flowVars.var2[?($.bkAuthorID == authorId)] map {
bookName:$.bkName,
bookDescription:$.bkDescription
}
}
})
}
Output:
{
"books": [
{
"bookAuthor": "abc",
"bookCategorys": [
{
"bookCategory": "horror",
"listOfBooks": [
{
"bookName": "gjh",
"bookDescription": "kjh"
},
{
"bookName": "sfs",
"bookDescription": "kjh"
}
]
},
{
"bookCategory": "comedy",
"listOfBooks": [
{
"bookName": "gjh",
"bookDescription": "kjh"
},
{
"bookName": "sfs",
"bookDescription": "kjh"
}
]
}
]
},
{
"bookAuthor": "xyz",
"bookCategorys": [
{
"bookCategory": "horror",
"listOfBooks": [
{
"bookName": "gjh",
"bookDescription": "kjh"
},
{
"bookName": "gjh",
"bookDescription": "kjh"
}
]
},
{
"bookCategory": "Fantacy",
"listOfBooks": [
{
"bookName": "gjh",
"bookDescription": "kjh"
},
{
"bookName": "gjh",
"bookDescription": "kjh"
}
]
}
]
}
]
}

Related

How can I create a hierarchical json response in FLASK

I have a single table in database like database table. I want to search a child from database and return a hierarchical JSON to a front end in order to create a tree. How can I do that in FLASK.
My expected JSON for mat should be like expected JSON
Since you have tagged your question with flask, this post assumes you are using Python as well. To format your database values in JSON string, you can query the db and then use recursion:
import sqlite3, collections
d = list(sqlite3.connect('file.db').cursor().execute("select * from values"))
def get_tree(vals):
_d = collections.defaultdict(list)
for a, *b in vals:
_d[a].append(b)
return [{'name':a, **({} if not (c:=list(filter(None, b))) else {'children':get_tree(b)})} for a, b in _d.items()]
import json
print(json.dumps(get_tree(d), indent=4))
Output:
[
{
"name": "AA",
"children": [
{
"name": "BB",
"children": [
{
"name": "EE",
"children": [
{
"name": "JJ",
"children": [
{
"name": "EEV"
},
{
"name": "FFW"
}
]
},
{
"name": "KK",
"children": [
{
"name": "HHX"
}
]
}
]
}
]
},
{
"name": "CC",
"children": [
{
"name": "FF",
"children": [
{
"name": "LL",
"children": [
{
"name": "QQY"
}
]
},
{
"name": "MM",
"children": [
{
"name": "RRV"
}
]
}
]
},
{
"name": "GG",
"children": [
{
"name": "NN",
"children": [
{
"name": "SSW"
}
]
}
]
}
]
},
{
"name": "DD",
"children": [
{
"name": "HH",
"children": [
{
"name": "OO",
"children": [
{
"name": "TTZ"
}
]
}
]
},
{
"name": "II",
"children": [
{
"name": "PP",
"children": [
{
"name": "UUW"
}
]
}
]
}
]
}
]
}
]

MongoDB reduce nested

I have a collection of a class that looks something like that:
[
{
"_id": 1,
"title": "dummy title",
"assignments": [
{
"_id": 1,
"name": "a1",
"members": [
{
"_id": 11,
"full_name": "john doe",
"aga": 18
},
{
"_id": 12,
"full_name": "john doe2",
"aga": 18
}
]
}
],
"settings": [
{
"type": "light",
"status": "enabled"
},
{
"type": "flare",
"status": "disabled"
},
{
"type": "toolbar",
"status": "enabled"
}
]
}
]
I have 2 nested documents here "assignments" which have a nested "members"
and "settings". the result i want should look something like that:
{
"_id": 1,
"title": "dummy title",
"assignments": [
{
"_id": 1,
"name": "a1",
"member_ids": [11, 18]
}
],
"active_settings": ["light", "toolbar"]
}
Meaning in each "assignment" I should only return the ids of the members and not the whole member data. and in settings I should only return the settings that are set to "active"
is it possible?
Playground here:
https://mongoplayground.net/p/Le4BdTm_gOv
You can try with $map to go one by one. $mergeObjects helps to merge the output value with same object
[
{
$project: {
title: 1,
assignments: {
$map: {
input: "$assignments",
in: {
$mergeObjects: [
"$$this",
{
members: {
$map: {
input: "$$this.members",
in: "$$this._id"
}
}
}
]
}
}
},
active_settings: {
$reduce: {
input: "$settings",
initialValue: [],
in: {
$cond: [
{
$eq: [
"$$this.status",
"enabled"
]
},
{
$setUnion: [
"$$value",
[
"$$this.type"
]
]
},
"$$value"
]
}
}
}
}
}
]
Working Mongo playground
You can try,
get assignments member ids using $map and $reduce
get active_settings using $reduce
db.collection.aggregate([
{
$project: {
_id: 1,
title: 1,
assignments: {
$map: {
input: "$assignments",
in: {
_id: "$$this._id",
name: "$$this.name",
memberIds: {
$reduce: {
input: "$$this.members",
initialValue: [],
in: { $concatArrays: ["$$value", ["$$this._id"]] }
}
}
}
}
},
active_settings: {
$reduce: {
input: "$settings",
initialValue: [],
in: {
$cond: [
{ $eq: ["$$this.status", "enabled"] },
{ $concatArrays: ["$$value", ["$$this.type"]] },
"$$value"
]
}
}
}
}
}
])
Playground

read hyperopt parameters from json

I want to read hyperopt parameters from a JSON file.
My JSON file would be like:
[
{
"id": "121",
"model": [
{
"model_name": "power",
"estimator_type": [
{
"type": "Polynomial",
"degree": [2, 3, 4]
},
{
"type": "svm",
"C": [0, 1],
"kernel": [
{
"ktype": "linear"
},
{
"ktype": "RBF",
"width": [0, 1]
}
]
}
],
"cut_values": {
"qids": ["1234"]
}
},
{
"model_name": "speed",
"estimator_type": [
{
"type": "Polynomial",
"degree": ["quniform", 2, 3]
}
],
"cut_values": null
}
]
},
{
"id": "123",
"model": [
{
"model_name": "power",
"estimator_type": [
{
"type": "LinearRegression"
}
],
"cut_values": null
}
]
}
]
I have checked this post but with no success for more complex JSON like the one above.
I want to be able to create a space like 2.2 A Search Space Example: scikit-learn.

Recurse for object if exists in JQ

I have the following structure:
{
"hits":
[
{
"_index": "main"
},
{
"_index": "main",
"accordions": [
{
"id": "1",
"accordionBody": "body1",
"accordionInnerButtonTexts": [
"button11",
"button12"
]
},
{
"id": "2",
"accordionBody": "body2",
"accordionInnerButtonTexts": [
"button21",
"button22"
]
}
]
}
]
}
I want to get to this structure:
{
"index": "main"
}
{
"index": "main",
"accordions":
[
{
"id": "1",
"accordionBody": "body1",
"accordionInnerButtonTexts": [
"button11",
"button12"
]
},
{
"id": "2",
"accordionBody": "body2",
"accordionInnerButtonTexts": [
"button21",
"button22"
]
}
]
}
Which means that I always want to include the _index-field as index, and I want to include the whole accordions-list IF IT EXISTS in the object. Here is my attempt:
.hits[] | {index: ._index, accordions: recurse(.accordions[]?)}
It does not produce what I want:
{
"index": "main",
"accordions": {
"_index": "main"
}
}
{
"index": "main",
"accordions": {
"_index": "main",
"accordions": [
{
"id": "1",
"accordionBody": "body1",
"accordionInnerButtonTexts": [
"button11",
"button12"
]
},
{
"id": "2",
"accordionBody": "body2",
"accordionInnerButtonTexts": [
"button21",
"button22"
]
}
]
}
}
{
"index": "main",
"accordions": {
"id": "1",
"accordionBody": "body1",
"accordionInnerButtonTexts": [
"button11",
"button12"
]
}
}
{
"index": "main",
"accordions": {
"id": "2",
"accordionBody": "body2",
"accordionInnerButtonTexts": [
"button21",
"button22"
]
}
}
It seems to create a list of all different permutations given by mixing the objects. This is not what I want. What is the correct jq command, and what is my mistake?
The problem as stated does not require any recursion. Using your attempt as a model, one could in fact simply write:
.hits[]
| {index: ._index}
+ (if has("accordions") then {accordions} else {} end)
Or, with quite different semantics:
.hits[] | {index: ._index} + . | del(._index)

Mapping complex Observable json to class or interface

I have an API I am consuming with a service in Angular 8.0.0. I cannot seem to understand how to map the json returned to an object.
All of the examples I have seen have been simple examples of an array of clearly defined and easily traversed json. The json set I am getting back is quite complex.
Ideally, since there is a lot of repeated patterns in there, I would make a class with other classes as members of the class.
Is there a way to just transform the returned observable json into the associated dictionary of dictionaries?
If I were to template this, I'm struggling with the fact that I get a dictionary back and not an array.
Here is the service design pattern that I am following. Since this design pattern transforms a simple json payload into a simple interface, it's not complex enough for me to try and transpose to my use-case. I have doubt on the ability to transform this complex dataset to an interface or class.
getTeams() {
return this.http.get<ITeam[]>(this._url).pipe(
retry(1), catchError(error => {
return throwError(error.message || 'Undefined Server Error');
}));
}
Here is my sample dataset similar to what I am trying to consume in my angular component via my service:
{
"stlouis_teams": {
"blues": {
"version": "12.0-57.24",
"image": "stl_team_photo.jpg",
"image_md5": "fffffc429735ffff4d6c716c113f3ffff",
"stadium_phones": {
"landlines": [
"210-555-1212",
"309-555-1212"
],
"cells": [
"312-555-1212",
"502-555-1212"
]
},
"coaching_staff": {
"coach": {
"image": "bill_brasky.jpg",
"image_locations": {
"http": [
"http://example.com/images/bill_brasky.jpg",
"http://example.com/bill_brasky.jpg"
],
"ftp": [
"ftp://example.com/public/images/bill_brasky.jpg",
"ftps://example.com/secure/aoe124/public/images/bill_brasky.jpg"
]
},
"image_md5": "4444444d0a2c1cad1437570f0e4444444"
},
"asst_coach": {
"image": "bill_billy.jpg",
"image_locations": {
"http": [
"http://example.com/images/bill_billy.jpg",
"http://example.com/bill_billy.jpg"
],
"ftp": [
"ftp://example.com/public/images/bill_billy.jpg",
"ftps://example.com/secure/aoe124/public/images/bill_billy.jpg"
]
},
"image_md5": "333333333d0a2c1cad1437570f0e33333333"
}
}
},
"jv_blues": {
"version": "1.0-0.0",
"image": "jv_stl_team_photo.jpg",
"image_md5": "9999c42973599994d6c716c113f39999",
"stadium_phones": {
"landlines": [
"210-555-1111",
"309-555-1111"
],
"cells": [
"312-555-1111",
"502-555-1111"
]
},
"coaching_staff": {
"coach": {
"image": "bill_brasky.jpg",
"image_locations": {
"http": [
"http://example.com/images/bill_brasky.jpg",
"http://example.com/bill_brasky.jpg"
],
"ftp": [
"ftp://example.com/public/images/bill_brasky.jpg",
"ftps://example.com/secure/aoe124/public/images/bill_brasky.jpg"
]
},
"image_md5": "4444444d0a2c1cad1437570f0e4444444"
},
"asst_coach": {
"image": "bill_billy.jpg",
"image_locations": {
"http": [
"http://example.com/images/bill_billy.jpg",
"http://example.com/bill_billy.jpg"
],
"ftp": [
"ftp://example.com/public/images/bill_billy.jpg",
"ftps://example.com/secure/aoe124/public/images/bill_billy.jpg"
]
},
"image_md5": "333333333d0a2c1cad1437570f0e33333333"
}
}
}
},
"chicago_teams": {
"blackhawks": {
"version": "11.33",
"image": "chi_team_photo.jpg",
"image_md5": "00000c42973500004d6c716c113f30000",
"stadium_phones": {
"landlines": [
"702-555-1212",
"412-555-1212"
],
"cells": [
"217-555-1212",
"904-555-1212"
]
},
"coaching_staff": {
"coach": {
"image": "bill_brasky.jpg",
"image_locations": {
"http": [
"http://example.com/images/bill_brasky.jpg",
"http://example.com/bill_brasky.jpg"
],
"ftp": [
"ftp://example.com/public/images/bill_brasky.jpg",
"ftps://example.com/secure/aoe124/public/images/bill_brasky.jpg"
]
},
"image_md5": "4444444d0a2c1cad1437570f0e4444444"
},
"asst_coach": {
"image": "bill_billy.jpg",
"image_locations": {
"http": [
"http://example.com/images/bill_billy.jpg",
"http://example.com/bill_billy.jpg"
],
"ftp": [
"ftp://example.com/public/images/bill_billy.jpg",
"ftps://example.com/secure/aoe124/public/images/bill_billy.jpg"
]
},
"image_md5": "333333333d0a2c1cad1437570f0e33333333"
}
}
},
"minor_blackhawks": {
"version": "1002.2",
"image": "minor_chi_team_photo.jpg",
"image_md5": "ccccccc42973500004d6c716c113fccccc",
"stadium_phones": {
"landlines": [
"702-555-2222",
"412-555-2222"
],
"cells": [
"217-555-2222",
"904-555-2222"
]
},
"coaching_staff": {
"coach": {
"image": "bill_brasky.jpg",
"image_locations": {
"http": [
"http://example.com/images/bill_brasky.jpg",
"http://example.com/bill_brasky.jpg"
],
"ftp": [
"ftp://example.com/public/images/bill_brasky.jpg",
"ftps://example.com/secure/aoe124/public/images/bill_brasky.jpg"
]
},
"image_md5": "4444444d0a2c1cad1437570f0e4444444"
},
"asst_coach": {
"image": "bill_billy.jpg",
"image_locations": {
"http": [
"http://example.com/images/bill_billy.jpg",
"http://example.com/bill_billy.jpg"
],
"ftp": [
"ftp://example.com/public/images/bill_billy.jpg",
"ftps://example.com/secure/aoe124/public/images/bill_billy.jpg"
]
},
"image_md5": "333333333d0a2c1cad1437570f0e33333333"
}
}
}
}
}