Formatting JSON document to specification needed for visualization - javascript

I'm attempting to create a Google Chart based on data in Elastic Search. The JSON document needs to be in the following format:
{
"cols": [
{"id":"","label":"Lane","type":"string"},
{"id":"","label":"Routes","type":"number"}
],
"rows": [
{"c":[{"v":"M01"},{"v":4657}]},
{"c":[{"v":"M02"},{"v":4419}]},
{"c":[{"v":"M03"},{"v":4611}]},
{"c":[{"v":"M04"},{"v":4326}]},
{"c":[{"v":"M05"},{"v":4337}]},
{"c":[{"v":"M06"},{"v":5363}]}
]
}
My query (via ajax command) returns the following data:
$ curl http://localhost:9200/wcs/routes/_search?pretty=true -d '{"query_all":{}}}'
{
"took" : 2,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"failed" : 0
},
"hits" : {
"total" : 7,
"max_score" : 1.0,
"hits" : [ {
"_index" : "wcs",
"_type" : "routes",
"_id" : "4",
"_score" : 1.0, "_source" : {"lane":"M04","routes":"102"}
}, {
"_index" : "wcs",
"_type" : "routes",
"_id" : "5",
"_score" : 1.0, "_source" : {"lane":"M03","routes":"143"}
}, {
"_index" : "wcs",
"_type" : "routes",
"_id" : "1",
"_score" : 1.0, "_source" : {"lane":"M07","routes":"80"}
}, {
"_index" : "wcs",
"_type" : "routes",
"_id" : "6",
"_score" : 1.0, "_source" : {"lane":"M02","routes":"157"}
}, {
"_index" : "wcs",
"_type" : "routes",
"_id" : "2",
"_score" : 1.0, "_source" : {"lane":"M06","routes":"101"}
}, {
"_index" : "wcs",
"_type" : "routes",
"_id" : "7",
"_score" : 1.0, "_source" : {"lane":"M01","routes":"105"}
}, {
"_index" : "wcs",
"_type" : "routes",
"_id" : "3",
"_score" : 1.0, "_source" : {"lane":"M05","routes":"160"}
} ]
}
}
The HTML/JS that I'm attempting to run (and currently returns nothing) is as follows. Could someone provide some insight as to what I may be doing wrong? It would be greatly appreciated.
<html>
<head>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script type="text/javascript">
google.load('visualization', '1', {'packages':['corechart']});
google.setOnLoadCallback(drawChart);
function drawChart() {
var jsonData = $.ajax({
url: 'http://localhost:9200/wcs/routes/_search?pretty=true'
, type: 'POST'
, data :
JSON.stringify(
{
"query" : { "match_all" : {} }
})
, dataType : 'json'
async: false
});
var json = JSON.parse(jsonData);
var jdata = '{ "cols": [{"id":"", "label":"lane", "type": "string"},' + '{"id": "", "label": "routes", "type": "number"}],' + '"rows":[{"c": [{"v":' + json.hits[0].hits[0]._source.lane + '},{"v":' + json.hits[0].hits[0]._source.routes + '}]}]';
var data = new google.visualization.DataTable(jdata);
var chart = new google.visualization.PieChart(document.getElementById('piechart_div'));
chart.draw(data, {is3D: true, title: 'Multi Routes per Lane', width: 600, height: 440});
}
</script>
</head>
<body>
<input type="button" onclick = "drawChart()" value="test">
<div id="piechart_div"> </div>
</body>
</html>

add the success handler in the ajax call. Also as Felix King pointed out, google.visualization.DataTable expects an JavaScript Object - not a string
So move all this code
var jdata = '{ "cols": [{"id":"", "label":"lane", "type": "string"},' + '{"id": "", "label": "routes", "type": "number"}],' + '"rows":[{"c": [{"v":' + json.hits[0].hits[0]._source.lane + '},{"v":' + json.hits[0].hits[0]._source.routes + '}]}]';
var data = new google.visualization.DataTable(jdata);
var chart = new google.visualization.PieChart(document.getElementById('piechart_div'));
chart.draw(data, {is3D: true, title: 'Multi Routes per Lane', width: 600, height: 440});
into the success handler
$.ajax({
url: 'http://localhost:9200/wcs/routes/_search?pretty=true'
, type: 'POST'
, data :
JSON.stringify(
{
"query" : { "match_all" : {} }
})
, dataType : 'json'
, success : function (json){ // <-- json = javascript object since you set dataType to 'json'
// your object to pass to DataTable
var jdata = {
"cols": [{
"id": "",
"label": "lane",
"type": "string"
}, {
"id": "",
"label": "routes",
"type": "number"
}],
"rows": [{
"c": [{
"v": json.hits[0].hits[0]._source.lane
}, {
"v": json.hits[0].hits[0]._source.routes
}]
}]
};
var data = new google.visualization.DataTable(jdata);
var chart = new google.visualization.PieChart(document.getElementById('piechart_div'));
chart.draw(data, {is3D: true, title: 'Multi Routes per Lane', width: 600, height: 440});
}
});

Was able to do this with the following code (thanks dinjas):
var json;
$.ajax({
url: 'http://localhost:9200/wcs/routes/_search',
type: 'POST',
data :
JSON.stringify(
{
"query" : { "match_all" : {} }
}),
dataType : 'json',
async: false,
success: function(data){
json = data;
}
})
var jdata = {};
jdata.cols = [
{
"id": "",
"label": "Lane",
"type": "string"
},
{
"id": "",
"label": "Routes",
"type":"number"
}
];
jdata.rows = [
{
"c": [
{
"v": json.hits.hits[0]._source.lane
},
{
"v": json.hits.hits[0]._source.routes
}
]
}
];

Related

Complex mongodb data how to update

I'm trying to update show_seats.showByDate.shows.showSeats.seat_details.values.seat_status
this my code .........................................................................................................................................................
db.seats.updateOne({'show_seats.showByDate.shows.showSeats.seat_details.values._id':"62a9e044ec028e60180fe28a"},{$set:{'show_seats.showByDate.shows.showSeats.seat_details.values.seat_status' : true}})
.........................................................................................................................................................
please say what did i wrong**
{
"_id" : ObjectId("62a43ac2d7213c7233cd1dee"),
"totalShowByDay" : "2",
"totalShowDays" : 4,
"movieId" : ObjectId("62953ba3cb6ae625ec9433e6"),
"screenId" : ObjectId("6293b9638dde2d92658d5513"),
"createdAt" : 1654930114438,
"showId" : ObjectId("62a43ac2d7213c7233cd14ed"),
"show_seats" : [
{
"showByDate" : {
"ShowDate" : "2022-06-11",
"shows" : [
{
"showTime" : "2022-06-11T10:00",
"showSeats" : [
[
{
"category" : "CLASSIC",
"seat_details" : [
{
"key" : "A",
"values" : [
{
"_id" : ObjectId("62a43ac2d7213c7233cd14ee"),
"seat_number" : "1",
"tag_name" : "A",
"seat_status" : false,
"user_id" : false,
"price" : "140",
"seats_category" : "CLASSIC",
"show_time" : "2022-06-11T10:00"
},
,
{
"_id" : ObjectId("62a43ac2d7213c7233cd14ef"),
"seat_number" : "2",
"tag_name" : "A",
"seat_status" : false,
"user_id" : false,
"price" : "140",
"seats_category" : "CLASSIC",
"show_time" : "2022-06-11T10:00"
},
{
"_id" : ObjectId("62a43ac2d7213c7233cd14f0"),
"seat_number" : "3",
"tag_name" : "A",
"seat_status" : false,
"user_id" : false,
"price" : "140",
"seats_category" : "CLASSIC",
"show_time" : "2022-06-11T10:00",,
{
"_id" : ObjectId("62a43ac2d7213c7233cd14ef"),
"seat_number" : "2",
"tag_name" : "A",
"seat_status" : false,
"user_id" : false,
"price" : "140",
"seats_category" : "CLASSIC",
"show_time" : "2022-06-11T10:00"
},
{
"_id" : ObjectId("62a43ac2d7213c7233cd14f0"),
"seat_number" : "3",
"tag_name" : "A",
"seat_status" : false,
"user_id" : false,
"price" : "140",
"seats_category" : "CLASSIC",
"show_time" : "2022-06-11T10:00"
}
this is what i ended up doing, I need best solution
await db.getDb().collection(coll.seat).aggregate([
{
'$unwind': {
'path': '$show_seats'
}
}, {
'$unwind': {
'path': '$show_seats.showByDate.shows'
}
}, {
'$unwind': {
'path': '$show_seats.showByDate.shows.showSeats'
}
}, {
'$unwind': {
'path': '$show_seats.showByDate.shows.showSeats'
}
}, {
'$unwind': {
'path': '$show_seats.showByDate.shows.showSeats.seat_details'
}
}, {
'$unwind': {
'path': '$show_seats.showByDate.shows.showSeats.seat_details.values'
}
}, {
'$match': {
'show_seats.showByDate.shows.showSeats.seat_details.values._id': ObjectId("62a43ac2d7213c7233cd14ee")
}
}, {
$addFields: { "show_seats.showByDate.shows.showSeats.seat_details.values.seat_status": true }
}
])

Elasticsearch only one record based on userid?

In post index, postid is primary key and userid is foreign key.
i want all post but only post from one userid, such that only one user have the one post in results sort by postdate(optional latest first)
//Actual Result
[
{
userid: "u1",
postid: "p1"
},
{
userid: "u1",
postid: "p2"
},
{
userid: "u2",
postid: "p3"
},
{
userid: "u3",
postid: "p4"
},
{
userid: "u3",
postid: "p5"
},
{
userid: "u3",
postid: "p6"
}
]
needed as below
//Expecting Result
[
{
userid: "u1",
postid: "p1"
},
{
userid: "u2",
postid: "p3"
},
{
userid: "u3",
postid: "p4"
}
]
I think you can use top hit for this. Here the sample for this :
DELETE my-index-000001
PUT my-index-000001
{
"mappings": {
"properties": {
"userid": {
"type": "keyword"
},
"postid": {
"type": "keyword"
},
"postdate": {
"type": "date"
}
}
}
}
PUT my-index-000001/_doc/1
{"userid": "u1", "postid": "p1", "postdate": "2021-03-01"}
PUT my-index-000001/_doc/2
{"userid": "u1", "postid": "p2", "postdate": "2021-03-02"}
PUT my-index-000001/_doc/3
{"userid": "u2", "postid": "p3", "postdate": "2021-03-03"}
PUT my-index-000001/_doc/4
{"userid": "u3", "postid": "p4", "postdate": "2021-03-04"}
PUT my-index-000001/_doc/5
{"userid": "u3", "postid": "p5", "postdate": "2021-03-05"}
PUT my-index-000001/_doc/6
{"userid": "u3", "postid": "p6", "postdate": "2021-03-06"}
These are the sample index creating steps. And here the query :
GET my-index-000001/_search
{
"size": 0,
"aggs": {
"top_users": {
"terms": {
"field": "userid",
"size": 100
},
"aggs": {
"top": {
"top_hits": {
"sort": [
{
"postdate": {
"order": "desc"
}
}
],
"_source": {
"includes": [ "postdate", "postid" ]
},
"size": 1
}
}
}
}
}
}
And, inside the resultset you can see the top post for the every users inside the aggregations:
{
"took" : 3,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 6,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ ]
},
"aggregations" : {
"top_users" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "u3",
"doc_count" : 3,
"top" : {
"hits" : {
"total" : {
"value" : 3,
"relation" : "eq"
},
"max_score" : null,
"hits" : [
{
"_index" : "my-index-000001",
"_type" : "_doc",
"_id" : "6",
"_score" : null,
"_source" : {
"postdate" : "2021-03-06",
"postid" : "p6"
},
"sort" : [
1614988800000
]
}
]
}
}
},
{
"key" : "u1",
"doc_count" : 2,
"top" : {
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : null,
"hits" : [
{
"_index" : "my-index-000001",
"_type" : "_doc",
"_id" : "2",
"_score" : null,
"_source" : {
"postdate" : "2021-03-02",
"postid" : "p2"
},
"sort" : [
1614643200000
]
}
]
}
}
},
{
"key" : "u2",
"doc_count" : 1,
"top" : {
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : null,
"hits" : [
{
"_index" : "my-index-000001",
"_type" : "_doc",
"_id" : "3",
"_score" : null,
"_source" : {
"postdate" : "2021-03-03",
"postid" : "p3"
},
"sort" : [
1614729600000
]
}
]
}
}
}
]
}
}
}
Assuming an index mapping of the form:
PUT user_posts
{
"mappings": {
"properties": {
"userid": {
"type": "keyword"
},
"postid": {
"type": "keyword"
},
"postdate": {
"type": "date"
}
}
}
}
You could:
aggregate on the userid and order the IDs alphabetically
sub-aggregate on the postid and sort the post by posttime descending via a max aggregation.
filter the response through the filter_path option to only retrieve what you need
POST user_posts/_search?filter_path=aggregations.*.buckets.key,aggregations.*.buckets.*.buckets.key
{
"size": 0,
"aggs": {
"by_userid": {
"terms": {
"field": "userid",
"order": {
"_key": "asc"
},
"size": 100
},
"aggs": {
"by_latest_postid": {
"terms": {
"field": "postid",
"size": 1,
"order": {
"latest_posttime": "desc"
}
},
"aggs": {
"latest_posttime": {
"max": {
"field": "postdate"
}
}
}
}
}
}
}
}
Yielding:
{
"aggregations" : {
"by_userid" : {
"buckets" : [
{
"key" : "u1",
"by_latest_postid" : {
"buckets" : [
{
"key" : "p1"
}
]
}
},
{
"key" : "u2",
"by_latest_postid" : {
"buckets" : [
{
"key" : "p3"
}
]
}
},
{
"key" : "u3",
"by_latest_postid" : {
"buckets" : [
{
"key" : "p4"
}
]
}
}
]
}
}
}
which you can then post-process as you normally would:
...
const response = await ...; // transform the above request for use in the ES JS lib of your choice
const result = response.aggregations.by_userid.buckets.map(b => {
return {
userid: b.key,
postid: b.by_latest_postid.buckets && b.by_latest_postid.buckets[0].key
}
})
You can use the top hits sub-aggregation. So first do a terms aggregation by userId, then you can use top-hits with a sort by post-date to get the latest post by each user.
I should say that if you have many userIds and you want the top hit for each one, you should probably use composite aggregation as your top-level agg, and not terms.

Elasticsearch sorting by custom item weight

I have stored the documents which include status property. I would like to sort the documents by status priority (not status alphabetically). I have followed previous answers and composed the following function which still doesnt work as expected; the documents are sorted by status names (alphabetically):
function getESSortingByStatusQuery(query, order) {
let statusOrder = ['BLUE', 'RED', 'BLACK', 'YELLOW', 'GREEN'];
if(order == 'desc'){
statusOrder.reverse();
}
const functions = statusOrder.map((item) => {
const idx = statusOrder.indexOf(item);
return {filter: {match: {statusColor: item}},
weight: (idx + 1) * 50}
});
const queryModified = {
"function_score": {
"query": {"match_all": {}}, // this is for testing purposes and should be replaced with original query
"boost": "5",
"functions": functions,
"score_mode": "multiply",
"boost_mode": "replace"
}
}
return queryModified;
}
I would be thankful if anyone suggested the way to sort items according to predefined priority of the property (in this case status).
Below is a sample custom sort script which I think is what you are looking for. I've added sample mapping, documents, query and the response as how it appears.
Mapping:
PUT color_index
{
"mappings": {
"properties": {
"color":{
"type": "keyword"
},
"product":{
"type": "text"
}
}
}
}
Sample Documents:
POST color_index/_doc/1
{
"color": "BLUE",
"product": "adidas and nike"
}
POST color_index/_doc/2
{
"color": "GREEN",
"product": "adidas and nike and puma"
}
POST color_index/_doc/3
{
"color": "GREEN",
"product": "adidas and nike"
}
POST color_index/_doc/4
{
"color": "RED",
"product": "nike"
}
POST color_index/_doc/5
{
"color": "RED",
"product": "adidas and nike"
}
Query:
POST color_index/_search
{
"query": {
"bool": {
"must": [
{
"query_string": {
"default_field": "*",
"query": "adidas OR nike"
}
}
]
}
},
"sort": [
{ "_score": { "order": "desc"} }, <---- First sort by score
{ "_script": { <---- Second sort by Colors
"type": "number",
"script": {
"lang": "painless",
"source": "if(params.scores.containsKey(doc['color'].value)) { return params.scores[doc['color'].value];} return 100000;",
"params": {
"scores": {
"BLUE": 0,
"RED": 1,
"BLACK": 2,
"YELLOW": 3,
"GREEN": 4
}
}
},
"order": "asc"
}
}
]
}
Firstly it would return documents sorted by its score, and then it would apply the second sorting logic to that result.
For the second sorting, i.e. using script sort, notice how I have added the numeric values to the colors in the scores section. You would need to construct your query accordingly.
The logic as how it works is in the source section which I believe is self-explainable, where I used doc['color'].value as that was my field on which I'm applying custom sort logic.
Response:
{
"took" : 5,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 5,
"relation" : "eq"
},
"max_score" : null,
"hits" : [
{
"_index" : "color_index",
"_type" : "_doc",
"_id" : "1",
"_score" : 0.5159407,
"_source" : {
"color" : "BLUE",
"product" : "adidas and nike"
},
"sort" : [
0.5159407, <--- This value is score(desc by nature)
0.0 <--- This value comes from script sort as its BLUE and I've used value 0 in the script which is in 'asc' order
]
},
{
"_index" : "color_index",
"_type" : "_doc",
"_id" : "5",
"_score" : 0.5159407,
"_source" : {
"color" : "RED",
"product" : "adidas and nike"
},
"sort" : [
0.5159407,
1.0
]
},
{
"_index" : "color_index",
"_type" : "_doc",
"_id" : "3",
"_score" : 0.5159407,
"_source" : {
"color" : "GREEN",
"product" : "adidas and nike"
},
"sort" : [
0.5159407,
4.0
]
},
{
"_index" : "color_index",
"_type" : "_doc",
"_id" : "2",
"_score" : 0.40538198,
"_source" : {
"color" : "GREEN",
"product" : "adidas and nike and puma"
},
"sort" : [
0.40538198,
4.0
]
},
{
"_index" : "color_index",
"_type" : "_doc",
"_id" : "4",
"_score" : 0.10189847,
"_source" : {
"color" : "RED",
"product" : "nike"
},
"sort" : [
0.10189847,
1.0
]
}
]
}
}
Notice the first three documents, it has exact value of product but different color and you can see that they are grouped together as we first sorted by _score then we sort that by color
Let me know if this helps!
Here's the code sample of sorting result. I think this will helps you. If you don't want to get entire documents as result you can filter results using includes.
GET testindex/_search
{
"_source": {
"includes": [
"filed1"
]
},
"aggs": {
"emp_figures": {
"terms": {
"field": "status"
}
}
}
}
This is the sample result you should retrieve
{
"took": 11,
"timed_out": false,
"_shards": {
"total": 2,
"successful": 2,
"failed": 0
},
"hits": {
"total": 84968,
"max_score": 1,
"hits": [
{
"_index": "test",
"_type": "type",
"_id": "0001",
"_score": 1,
"_source": {
"filed1": "color1,
}
},
{
"_index": "test",
"_type": "type",
"_id": "0002",
"_score": 1,
"_source": {
"filed1": "color2,
}
}
}
}
}

Need to remove duplication in array of objects and merge array with union USING JS

Need to remove duplication in array of objects and merge array with union USING JS.
trying to filter array
Just wanted to merge array["INTERFACE"] on the basis of APP_ID. and remove duplicate records.
unfiltered unmerged array!
var data = [
{
"APP_ID" : "1001",
"INTERFACE" : [
{
"INTERFACE_ID" : "01",
"NAME" : "CIF OPENNING",
"URL" : "/CusIdInfo",
"STATUS" : "A"
},
{
"INTERFACE_ID" : "07",
"NAME" : "DASHBOARD",
"URL" : "/Dashboard",
"STATUS" : "A"
},
{
"INTERFACE_ID" : "06",
"NAME" : "SUMMARY COPC",
"URL" : "/SummaryCopc",
"STATUS" : "A"
}
]
},
{
"APP_ID" : "1002",
"INTERFACE" : [
{
"INTERFACE_ID" : "07",
"NAME" : "DASHBOARD",
"URL" : "/Dashboard",
"STATUS" : "A"
},
{
"INTERFACE_ID" : "08",
"NAME" : "BIOMETRIC",
"URL" : "/Biometric",
"STATUS" : "A"
}
]
},
{
"APP_ID" : "1001",
"INTERFACE" : [
{
"INTERFACE_ID" : "01",
"NAME" : "CIF OPENNING",
"URL" : "/CusIdInfo",
"STATUS" : "A"
},
{
"INTERFACE_ID" : "05",
"NAME" : "SUMMARY",
"URL" : "/Summary",
"STATUS" : "A"
},
{
"INTERFACE_ID" : "06",
"NAME" : "SUMMARY COPC 2",
"URL" : "/SummaryCopc2",
"STATUS" : "A"
},
{
"INTERFACE_ID" : "07",
"NAME" : "DASHBOARD 2",
"URL" : "/Dashboard 2",
"STATUS" : "A"
}
]
},
{
"APP_ID" : "1002",
"INTERFACE" : [
{
"INTERFACE_ID" : "07",
"NAME" : "DASHBOARD",
"URL" : "/Dashboard",
"STATUS" : "A"
},
{
"INTERFACE_ID" : "08",
"NAME" : "BIOMETRIC",
"URL" : "/Biometric",
"STATUS" : "A"
}
]
}
];
wanted result
[
{
"APP_ID" : "1002",
"INTERFACE" : [
{
"INTERFACE_ID" : "07",
"NAME" : "DASHBOARD",
"URL" : "/Dashboard",
"STATUS" : "A"
},
{
"INTERFACE_ID" : "08",
"NAME" : "BIOMETRIC",
"URL" : "/Biometric",
"STATUS" : "A"
}
]
},
{
"APP_ID" : "1001",
"INTERFACE" : [
{
"INTERFACE_ID" : "01",
"NAME" : "CIF OPENNING",
"URL" : "/CusIdInfo",
"STATUS" : "A"
},
{
"INTERFACE_ID" : "05",
"NAME" : "SUMMARY",
"URL" : "/Summary",
"STATUS" : "A"
},
{
"INTERFACE_ID" : "06",
"NAME" : "SUMMARY COPC",
"URL" : "/SummaryCopc",
"STATUS" : "A"
},
{
"INTERFACE_ID" : "07",
"NAME" : "DASHBOARD",
"URL" : "/Dashboard",
"STATUS" : "A"
}, {
"INTERFACE_ID" : "07",
"NAME" : "DASHBOARD 2",
"URL" : "/Dashboard2",
"STATUS" : "A"
},
{
"INTERFACE_ID" : "06",
"NAME" : "SUMMARY COPC 2",
"URL" : "/SummaryCopc2",
"STATUS" : "A"
}
]
}
]
trying to filter array
Just wanted to merge array["INTERFACE"] on the basis of APP_ID. and remove duplicate records.
Here is a slightly elastic solution relying on function generators that allows dynamic aggregation.
The logic followed by the below example is that in your data input, the unique key of the main objects is APP_ID. Next, the aggregation rule of each APP_ID is that it should follow another aggregation rule for INTERFACE. Each interface, in fact, has a unique NAME, explaining why you have multiple "07" and "06" in your result sample.
The code explanation is documented in the code itself.
var data = [
{
"APP_ID" : "1001",
"INTERFACE" : [
{
"INTERFACE_ID" : "01",
"NAME" : "CIF OPENNING",
"URL" : "/CusIdInfo",
"STATUS" : "A"
},
{
"INTERFACE_ID" : "07",
"NAME" : "DASHBOARD",
"URL" : "/Dashboard",
"STATUS" : "A"
},
{
"INTERFACE_ID" : "06",
"NAME" : "SUMMARY COPC",
"URL" : "/SummaryCopc",
"STATUS" : "A"
}
]
},
{
"APP_ID" : "1002",
"INTERFACE" : [
{
"INTERFACE_ID" : "07",
"NAME" : "DASHBOARD",
"URL" : "/Dashboard",
"STATUS" : "A"
},
{
"INTERFACE_ID" : "08",
"NAME" : "BIOMETRIC",
"URL" : "/Biometric",
"STATUS" : "A"
}
]
},
{
"APP_ID" : "1001",
"INTERFACE" : [
{
"INTERFACE_ID" : "01",
"NAME" : "CIF OPENNING",
"URL" : "/CusIdInfo",
"STATUS" : "A"
},
{
"INTERFACE_ID" : "05",
"NAME" : "SUMMARY",
"URL" : "/Summary",
"STATUS" : "A"
},
{
"INTERFACE_ID" : "06",
"NAME" : "SUMMARY COPC 2",
"URL" : "/SummaryCopc2",
"STATUS" : "A"
},
{
"INTERFACE_ID" : "07",
"NAME" : "DASHBOARD 2",
"URL" : "/Dashboard 2",
"STATUS" : "A"
}
]
},
{
"APP_ID" : "1002",
"INTERFACE" : [
{
"INTERFACE_ID" : "07",
"NAME" : "DASHBOARD",
"URL" : "/Dashboard",
"STATUS" : "A"
},
{
"INTERFACE_ID" : "08",
"NAME" : "BIOMETRIC",
"URL" : "/Biometric",
"STATUS" : "A"
}
]
}
];
// Aggregate duplicates with a common uniqueKey, invoking the aggregateExpression callback for each pair.
function* aggregateDuplicates(arr, uniqueKey, aggregateExpression) {
const aggregateGroups = arr.reduce((acc,next) => {
acc[next[uniqueKey]] = acc[next[uniqueKey]] || [];
return acc[next[uniqueKey]].push(next), acc;
}, {});
// loop items.
for (var [_, entries] of Object.entries(aggregateGroups)) {
// Aggregate results following the aggregateExpression.
yield Object.assign({}, entries.reduce((acc, next) => aggregateExpression(acc, next)));
}
}
// Aggregate duplicates of data, whose unique key is APP_ID.
const res = [...aggregateDuplicates(data, 'APP_ID', (a,b) => {
// In order to properly aggregate the INTERFACE property, acquire the set of entires interfaces of two items with the same APP_ID.
var interfacesSet = [...a.INTERFACE, ...b.INTERFACE];
// Finally, spread common values between them, then aggregate the INTERFACE property by its unique NAME key.
return Object.assign(a, b, {
INTERFACE: [...aggregateDuplicates(interfacesSet, 'NAME', (c,d) => {
// For that NAME property, just assign the values of both objects, nothing more nothing less.
return Object.assign(c,d)
})]
});
})];
console.log(res);
SIDE NOTE: The sorting to the INTERFACE property is not applied, this is a plus, but I don't think it's mandatory as long as the output data is effectively correct.
// Create the array of APP_ID
let idArr = data.map(val => val.APP_ID)
// Remove duplicate APP_ID
idArr = [...new Set(idArr)];
// Filter data according to unique APP_IDs
let newArr = idArr.map(val => {
return data.filter(value => value.APP_ID == val)[0]
})
console.log(newArr);
Solution
Here is a quick solution that I was able to come up with,
Note that this solution takes care of union of INTERFACES within the same APP_ID
const data = [
{
APP_ID: '1001',
INTERFACE: [
{
INTERFACE_ID: '01',
NAME: 'CIF OPENNING',
URL: '/CusIdInfo',
STATUS: 'A',
},
{
INTERFACE_ID: '07',
NAME: 'DASHBOARD',
URL: '/Dashboard',
STATUS: 'A',
},
{
INTERFACE_ID: '06',
NAME: 'SUMMARY COPC',
URL: '/SummaryCopc',
STATUS: 'A',
},
],
},
{
APP_ID: '1002',
INTERFACE: [
{
INTERFACE_ID: '07',
NAME: 'DASHBOARD',
URL: '/Dashboard',
STATUS: 'A',
},
{
INTERFACE_ID: '08',
NAME: 'BIOMETRIC',
URL: '/Biometric',
STATUS: 'A',
},
],
},
{
APP_ID: '1001',
INTERFACE: [
{
INTERFACE_ID: '01',
NAME: 'CIF OPENNING',
URL: '/CusIdInfo',
STATUS: 'A',
},
{
INTERFACE_ID: '05',
NAME: 'SUMMARY',
URL: '/Summary',
STATUS: 'A',
},
{
INTERFACE_ID: '06',
NAME: 'SUMMARY COPC 2',
URL: '/SummaryCopc2',
STATUS: 'A',
},
{
INTERFACE_ID: '07',
NAME: 'DASHBOARD 2',
URL: '/Dashboard 2',
STATUS: 'A',
},
],
},
{
APP_ID: '1002',
INTERFACE: [
{
INTERFACE_ID: '07',
NAME: 'DASHBOARD',
URL: '/Dashboard',
STATUS: 'A',
},
{
INTERFACE_ID: '08',
NAME: 'BIOMETRIC',
URL: '/Biometric',
STATUS: 'A',
},
],
},
];
const result = {};
data.forEach(elem => {
if (!result[elem.APP_ID]) {
result[elem.APP_ID] = {};
result[elem.APP_ID].APP_ID = elem.APP_ID;
result[elem.APP_ID].INTERFACE = elem.INTERFACE;
} else {
const interfaces = result[elem.APP_ID].INTERFACE;
for (const elemInterface of elem.INTERFACE) {
if (
!interfaces.some(inter => {
return elemInterface.INTERFACE_ID === inter.INTERFACE_ID;
})
) {
interfaces.push(elemInterface);
}
}
}
});
console.log('TCL: results', Object.values(result));
Assumptions:
Since you stated that you wanted union of the interfaces within the same APP_ID I assume that there should be no duplicate interfaces
Example: If there is an interface array A1,
[
{
INTERFACE_ID: '01',
NAME: 'CIF OPENNING',
URL: '/CusIdInfo',
STATUS: 'A',
},
{
INTERFACE_ID: '07',
NAME: 'DASHBOARD',
URL: '/Dashboard',
STATUS: 'A',
},
{
INTERFACE_ID: '06',
NAME: 'SUMMARY COPC',
URL: '/SummaryCopc',
STATUS: 'A',
},
]
and another interface array A2,
[
{
INTERFACE_ID: '01',
NAME: 'CIF OPENNING',
URL: '/CusIdInfo',
STATUS: 'A',
},
{
INTERFACE_ID: '05',
NAME: 'SUMMARY',
URL: '/Summary',
STATUS: 'A',
},
{
INTERFACE_ID: '06',
NAME: 'SUMMARY COPC 2',
URL: '/SummaryCopc2',
STATUS: 'A',
},
{
INTERFACE_ID: '07',
NAME: 'DASHBOARD 2',
URL: '/Dashboard 2',
STATUS: 'A',
},
]
Then A1 union A2 would be,
[
{
"INTERFACE_ID": "01",
"NAME": "CIF OPENNING",
"URL": "/CusIdInfo",
"STATUS": "A"
},
{
"INTERFACE_ID": "07",
"NAME": "DASHBOARD",
"URL": "/Dashboard",
"STATUS": "A"
},
{
"INTERFACE_ID": "06",
"NAME": "SUMMARY COPC",
"URL": "/SummaryCopc",
"STATUS": "A"
},
{
"INTERFACE_ID": "05",
"NAME": "SUMMARY",
"URL": "/Summary",
"STATUS": "A"
}
]
Note that there are no duplicates.
My second assumption is that when you check for duplicity in interfaces you use the INTERFACE_ID and not the whole interface object.
Example: Assume an interface object I1,
{
INTERFACE_ID: '01',
NAME: 'CIF OPENNING',
URL: '/CusIdInfo',
STATUS: 'A',
}
and another interface object I2 with the only difference being that it has a different status value which is 'B',
{
INTERFACE_ID: '01',
NAME: 'CIF OPENNING',
URL: '/CusIdInfo',
STATUS: 'B',
}
I am still considering I1 and I2 to be duplicates based on their INTERFACE_ID.
Suppose you want to compare entire object for duplicity then update your question and I shall change the answer to factor it in
Came up with this solution. Hope this works for you.
NOTE : In the expected result array you have 2 interface objects with same ID so i am assuming that two interface are duplicate only if all their properties match.
var data = [
{
"APP_ID" : "1001",
"INTERFACE" : [
{
"INTERFACE_ID" : "01",
"NAME" : "CIF OPENNING",
"URL" : "/CusIdInfo",
"STATUS" : "A"
},
{
"INTERFACE_ID" : "07",
"NAME" : "DASHBOARD",
"URL" : "/Dashboard",
"STATUS" : "A"
},
{
"INTERFACE_ID" : "06",
"NAME" : "SUMMARY COPC",
"URL" : "/SummaryCopc",
"STATUS" : "A"
}
]
},
{
"APP_ID" : "1002",
"INTERFACE" : [
{
"INTERFACE_ID" : "07",
"NAME" : "DASHBOARD",
"URL" : "/Dashboard",
"STATUS" : "A"
},
{
"INTERFACE_ID" : "08",
"NAME" : "BIOMETRIC",
"URL" : "/Biometric",
"STATUS" : "A"
}
]
},
{
"APP_ID" : "1001",
"INTERFACE" : [
{
"INTERFACE_ID" : "01",
"NAME" : "CIF OPENNING",
"URL" : "/CusIdInfo",
"STATUS" : "A"
},
{
"INTERFACE_ID" : "05",
"NAME" : "SUMMARY",
"URL" : "/Summary",
"STATUS" : "A"
},
{
"INTERFACE_ID" : "06",
"NAME" : "SUMMARY COPC 2",
"URL" : "/SummaryCopc2",
"STATUS" : "A"
},
{
"INTERFACE_ID" : "07",
"NAME" : "DASHBOARD 2",
"URL" : "/Dashboard 2",
"STATUS" : "A"
}
]
},
{
"APP_ID" : "1002",
"INTERFACE" : [
{
"INTERFACE_ID" : "07",
"NAME" : "DASHBOARD",
"URL" : "/Dashboard",
"STATUS" : "A"
},
{
"INTERFACE_ID" : "08",
"NAME" : "BIOMETRIC",
"URL" : "/Biometric",
"STATUS" : "A"
}
]
}
];
isInterfaceDuplicate = function(interface, app_id) {
var keys = Object.keys(interface);
var isDuplicate = false;
app_map[app_id].forEach(app_obj => {
var matched = true;
keys.forEach(key => {
if (interface[key] !== app_obj[key]) {
matched = false;
return;
}
});
if (matched) {
isDuplicate = true;
return;
}
});
return isDuplicate;
};
/* Create a mapping for APP_ID and INTERFACE */
var app_map = {};
data.forEach(app_obj => {
// If APP_ID is not present in map, then add in map directly.
if (!app_map[app_obj.APP_ID]) {
app_map[app_obj.APP_ID] = [...app_obj.INTERFACE];
return;
}
// If APP_ID is present in map, only add non duplicate interfaces in APP_ID key.
app_obj.INTERFACE.forEach(interface => {
var isDuplicate = isInterfaceDuplicate(interface, app_obj.APP_ID);
if (!isDuplicate) {
app_map[app_obj.APP_ID].push({...interface});
}
});
});
/* Create result array from the map */
var result = [];
Object.keys(app_map).forEach(app_id => {
result.push({
"APP_ID": app_id,
"INTERFACE": app_map[app_id]
});
});
console.log(result);

Multi options in select2

I am trying to use select2 to get remote JSON data and display it with mutli levels.
http://ivaynberg.github.io/select2/index.html
This is my response
{
"Company": [
{
"name": "athenahealth Inc"
},
{
"name": "Localiza Rent a Car"
},
{
"name": "M and B Switchgears"
}
],
"Functional": [
{
"name": "arranger"
},
{
"name": "ambassadors"
}
],
"Persons": [
{
"name": "Moustapha al"
},
{
"name": "Saleh al"
}
]
}
I want to show the result in Multi-Value format - http://ivaynberg.github.io/select2/index.html#multi
So far i am able to fetch data from server side , but then i have no idea how to enable the multi select option.
JSON in following format will work fine
Related issue - https://github.com/ivaynberg/select2/issues/58
{ "Data" : [ {
"id" :1 ,
"text" : "Subsection" ,
"children" : [{
"id" : 2,
"text" : "Paru"
},
{
"id" : 3,
"text" : "Vinu"
}]
},
{ "id" : 4 ,
"text" : "Family" ,
"children" : [{
"id" : 5,
"text" : "ChildVM"
},
{
"id" : 6,
"text" : "ChildPM"
}]
}
]
}

Categories

Resources