How to count the number of occurances in a json - java

I've the below JSON data.
{
"faceDetails": [
{
"boundingBox": {
"width": 0.36888888,
"height": 0.2777778,
"left": 0.4814815,
"top": 0.4422222
},
"emotions": [
{
"type": "SAD",
"confidence": 40.245743
},
{
"type": "CONFUSED",
"confidence": 15.142041
},
{
"type": "SURPRISED",
"confidence": 1.9677103
}
],
"smile": {
"value": false,
"confidence": 90.49947
}
},
{
"boundingBox": {
"width": 0.36888888,
"height": 0.2777778,
"left": 0.4814815,
"top": 0.4422222
},
"emotions": [
{
"type": "SAD",
"confidence": 40.245743
},
{
"type": "CONFUSED",
"confidence": 15.142041
},
{
"type": "SURPRISED",
"confidence": 1.9677103
}
],
"smile": {
"value": false,
"confidence": 90.49947
}
},
{
"boundingBox": {
"width": 0.36888888,
"height": 0.2777778,
"left": 0.4814815,
"top": 0.4422222
},
"emotions": [
{
"type": "SAD",
"confidence": 40.245743
},
{
"type": "CONFUSED",
"confidence": 15.142041
},
{
"type": "SURPRISED",
"confidence": 1.9677103
}
],
"smile": {
"value": false,
"confidence": 90.49947
}
},
{
"boundingBox": {
"width": 0.36888888,
"height": 0.2777778,
"left": 0.4814815,
"top": 0.4422222
},
"emotions": [
{
"type": "Happy",
"confidence": 40.245743
},
{
"type": "CONFUSED",
"confidence": 15.142041
},
{
"type": "SURPRISED",
"confidence": 1.9677103
}
],
"smile": {
"value": false,
"confidence": 90.49947
}
}
]
}
From this data I need to get the emotion with the top confidence score, create a variable and assign this score to that. For ex. from the above data, My output should be like below.
Happy: 1
Sad: 3
Here the order of printing doesn't matter. I'm asking you this because, I'm unable to understand on how to create a variable on the go. i.e. If there is another variable the type is cool, then I need a variable named cool and its count.
Also I'm unable to understand how to capture the emotions value
Below is the code that I tried
private static void getTheResultBasedOnEmotions(String inputText)
throws JsonParseException, JsonMappingException, IOException {
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> map = mapper.readValue(inputText, new TypeReference<Map<String, Object>>() {
});
List faceCount = (List) map.get("faceDetails");
System.out.println(faceCount.toString());
}
and the result that I get is as below
[
{
"boundingBox": {
"width": 0.36888888,
"height": 0.2777778,
"left": 0.4814815,
"top": 0.4422222
},
"emotions": [
{
"type": "SAD",
"confidence": 40.245743
},
{
"type": "CONFUSED",
"confidence": 15.142041
},
{
"type": "SURPRISED",
"confidence": 1.9677103
}
],
"smile": {
"value": false,
"confidence": 90.49947
}
},
{
"boundingBox": {
"width": 0.36888888,
"height": 0.2777778,
"left": 0.4814815,
"top": 0.4422222
},
"emotions": [
{
"type": "SAD",
"confidence": 40.245743
},
{
"type": "CONFUSED",
"confidence": 15.142041
},
{
"type": "SURPRISED",
"confidence": 1.9677103
}
],
"smile": {
"value": false,
"confidence": 90.49947
}
},
{
"boundingBox": {
"width": 0.36888888,
"height": 0.2777778,
"left": 0.4814815,
"top": 0.4422222
},
"emotions": [
{
"type": "SAD",
"confidence": 40.245743
},
{
"type": "CONFUSED",
"confidence": 15.142041
},
{
"type": "SURPRISED",
"confidence": 1.9677103
}
],
"smile": {
"value": false,
"confidence": 90.49947
}
},
{
"boundingBox": {
"width": 0.36888888,
"height": 0.2777778,
"left": 0.4814815,
"top": 0.4422222
},
"emotions": [
{
"type": "Happy",
"confidence": 40.245743
},
{
"type": "CONFUSED",
"confidence": 15.142041
},
{
"type": "SURPRISED",
"confidence": 1.9677103
}
],
"smile": {
"value": false,
"confidence": 90.49947
}
}
]
Please let me know how can I do this.
Here I use jackson file to parse.
Thanks

Here's my approach:
Parse JSON into POJO with help of Gson and Online POJO generator
PS.You can use any library, like jackson, to parse JSON to POJO.
//classes generated by Json2POJO generator
class FaceDetail {
private Object boundingBox;
private List<Emotion> emotions;
private Object smile;
public List<Emotion> getEmotions() {
return emotions;
}
}
class Emotion {
private String type;
private Double confidence;
public String getType() {
return type;
}
}
//Parse Json to POJO
List<FaceDetail> faceDetails = gson.fromJson(JSONData, ArrayList<FaceDetail>.class);
Count Emotion number by type with Java stream API
//Flap map all emotion to an ArrayList
List<Emotion> allEmotions = faceDetails.stream()
.map(FaceDetail::getEmotions)
.flatMap(emotions -> emotions.stream())
.collect(Collectors.toList());
//count
long countSAD = allEmotions.stream()
.filter(emotion -> emotion.getType().equals("SAD"))
.count();
Hope this could help:)

Related

jolt transformation of this complex scenario?

I want the jolt transform for the given input . Your help in this is highly appreciated . thanks i am providing the input and expected output. in input json Photos array is dynamic in nature. Here it is 3 , it can be 3 or 4 or5 any .
Input JSON :
{
"Entity": {
"card": {
"cardNo":"123456789",
"cardStatus":"10",
"cardAddress":"UK",
"cardAddress1":"US",
"cardCity":"mk" ,
"name": "RAM",
"lastName": "ABU",
"name1": "RAM1",
"lastName1": "ABU1"
},
"Photos": [
{
"Id": 327703,
"Caption": "TEST>> photo 1",
"Url": "http://bob.com/0001/327703/photo.jpg"
},
{
"Id": 327704,
"Caption": "TEST>> photo 2",
"Url": "http://bob.com/0001/327704/photo.jpg"
},
{
"Id": 327704,
"Caption": "TEST>> photo 2",
"Url": "http://bob.com/0001/327704/photo.jpg"
}
]
}
}
Used Jolt Spec :
[
{
"operation": "shift",
"spec": {
"Entity": {
"card": {
"cardNo": "tab.text",
"cardAddress": "address[0].add",
"cardAddress1": "address[0].add2",
"cardC*": "address[0].mk",
"Id1": "Photos.no",
"#http.1.com": "Photos.caption2",
"Id2": "Photos.no",
"#http.2.com": "Photos.caption2"
},
"Photos": {
"*": {
"Id": "Photos.no",
"Caption": "Photos.caption2"
}
}
}
}
},
{
"operation": "shift",
"spec": {
"tab": "&",
"address": "&",
"Photos": {
"*": {
"*": {
"#": "&3[&1].&2"
}
}
}
}
}
]
Current Output :
{
"tab": {
"text": "123456789"
},
"address": [
{
"add": "UK",
"add2": "US",
"mk": "mk"
}
],
"Photos": [
{
"caption2": "http.1.com",
"no": 222444
},
{
"caption2": "http.2.com",
"no": 222444
},
{
"caption2": "TEST>> photo 1",
"no": 327703
},
{
"caption2": "TEST>> photo 2",
"no": 327704
},
{
"caption2": "TEST>> photo 2",
"no": 327704
}
]
}
Expected Output ( i need "no" in string like below ) :
{
"tab": {
"text": "123456789"
},
"address": [
{
"add": "UK",
"add2": "US",
"mk": "mk"
}
],
"Photos": [
{
"caption2": "http.1.com",
"no": "222444"
},
{
"caption2": "http.2.com",
"no": "222444"
},
{
"caption2": "TEST>> photo 1",
"no": "327703"
},
{
"caption2": "TEST>> photo 2",
"no": "327704"
},
{
"caption2": "TEST>> photo 2",
"no": "327704"
}
]
}
You can add a modify transformation to the current spec along with toString function such as
,
{
"operation": "modify-overwrite-beta",
"spec": {
"Photos": {
"*": {
"no": "=toString"
}
}
}
}

Overriding existing property of json, or adding next if not present in json

I have some JSON, declared as string for my testing purposes in main method.
My goal is to use JSONPATH with DocumentContext, to override property if property exists, and to add it if it does not exists.
Is there possibility to achieve that ?
My JSON
How to add new node to Json using JsonPath?
Convert a JSON object to another JSON object in Java
I've visited these two but my result is not JSON but "com.jayway.jsonpath.internal.JsonReader#1ae369b7"
{
"meta": {
"drilldownEnabled": false
},
"chart": {
renderTo:"container",
"additionalData": {
"dateTime": false,
"datetype": "string",
"cliccable": true,
"drillable": false,
"drillableChart": false,
"isCockpit": true,
"categoryColumn": "periodo_analisi",
"categoryGroupBy": "",
"categoryGroupByNamens": "",
"categoryName": "periodo_analisi",
"categoryOrderColumn": "",
"categoryOrderType": "",
"categoryStacked": "",
"categoryStackedType": ""
},
"zoomType": "xy",
"panning": true,
"type": "column",
"options3d": {
"enabled": false,
"alpha": 25,
"beta": 15,
"depth": 50,
"viewDistance": 25
},
"backgroundColor": "#FFFFFF",
"heightDimType": "pixels",
"widthDimType": "pixels",
"plotBackgroundColor": null,
"plotBorderWidth": null,
"plotShadow": false,
"borderColor": "#FFFFFF",
"style": {
"backgroundColor": "#FFFFFF",
"fontFamily": "",
"fontWeight": "",
"fontSize": ""
},
"events": {}
},
"colors": [
"#ff5722"
],
"title": {
"text": "",
"style": {
"align": "",
"color": "",
"fontFamily": "",
"fontSize": "",
"fontWeight": ""
}
},
"legend": {
"enabled": false
},
"xAxis": [
{
"plotBands": [
{
"label": {
"text": "",
"align": "center"
},
"color": "",
"from": 0,
"to": 0
}
],
"plotLines": [
{
"label": {
"text": "",
"align": "center"
},
"color": "",
"dashStyle": "",
"value": 0,
"width": 0
}
],
"type": "category",
"id": 0,
"title": {
"customTitle": false,
"text": "periodo_analisi",
"style": {}
},
"labels": {
"style": {
"color": "",
"fontFamily": "",
"fontSize": "",
"fontWeight": ""
},
"align": ""
}
}
],
"yAxis": [
{
"plotBands": [
{
"label": {
"text": "",
"align": "center"
},
"color": "",
"from": 0,
"to": 0
}
],
"plotLines": [
{
"label": {
"text": "",
"align": "center"
},
"color": "",
"dashStyle": "",
"value": 0,
"width": 0,
"zIndex": 1
}
],
"title": {
"text": "NUM_GG_GIACENZA_AVG",
"customTitle": false,
"style": {
"color": "",
"fontFamily": "",
"fontWeight": "",
"fontSize": ""
}
},
"labels": {
"style": {
"color": "",
"fontFamily": "",
"fontSize": "",
"fontWeight": ""
},
"align": ""
},
"gridLineDashStyle": "$convertedTypeline",
"minorGridLineDashStyle": "$convertedMinorTpeline"
}
],
"series": [
{
"name": "NUM_GG_GIACENZA_AVG",
"dataLabels": {
"style": {
"color": "",
"fontFamily": "",
"fontWeight": "",
"fontSize": "",
"fontStyle": ""
},
"enabled": true,
"labelFormat": "{y:,.2f}"
},
"data": [
{
"drilldown": false,
"y": 32.6667,
"name": "Q1-2019",
"datetype": "string"
},
{
"drilldown": false,
"y": 29,
"name": "Q3-2018",
"datetype": "string"
},
{
"drilldown": false,
"y": 134.5,
"name": "Q4-2018",
"datetype": "string",
"color": "#F10AE8"
}
],
"selected": true,
"tooltip": {
"valueDecimals": 2,
"scaleFactor": "empty",
"ttBackColor": "#FCFFC5"
},
"yAxis": 0
}
],
"tooltip": {
"borderWidth": 0,
"borderRadius": 0,
"followTouchMove": false,
"followPointer": true,
"useHTML": true,
"backgroundColor": null,
"style": {
"padding": 0
}
},
"lang": {
"noData": ""
},
"noData": {
"style": {
"fontFamily": "",
"fontSize": "",
"color": ""
},
"position": {
"align": "center",
"verticalAlign": "middle"
}
},
"credits": {
"enabled": false
},
"plotOptions": {
"line": {
"marker": {
"symbol": "circle",
"lineWidth": 2
}
},
"column": {},
"bar": {},
"series": {
"cursor": "pointer",
"point": {
"events": {}
},
"dataLabels": {
"allowOverlap": true
},
"turboThreshold": 2000
}
}
}
I simply place this JSON in string as cc variable and write
DocumentContext doc = JsonPath.parse(cc).set(JsonPath.compile("$.meta"), "nani");
doc.json();
System.out.println(doc);
You're printing the DocumentContext instance instead of its content.
Try:
System.out.println(doc.read([Your JsonPath]));
Go here for more Info.

elasticsearch how to group by repetitive items in array without distinct

I'm trying to get the counts group by the repetitive items in array without distinct, use aggs terms but not work
GET /my_index/_search
{
"size": 0,
"aggs": {
"keywords": {
"terms": {
"field": "keywords"
}
}
}
}
documents like:
"keywords": [
"value1",
"value1",
"value2"
],
but the result is:
"buckets": [
{
"key": "value1",
"doc_count": 1
},
{
"key": "value2",
"doc_count": 1
}
]
how can i get the result like:
"buckets": [
{
"key": "value1",
"doc_count": 2
},
{
"key": "value2",
"doc_count": 1
}
]
finally I modify the mapping use nested:
"keywords": {
"type": "nested",
"properties": {
"count": {
"type": "integer"
},
"keyword": {
"type": "keyword"
}
}
},
and query:
GET /my_index/_search
{
"size": 0,
"aggs": {
"keywords": {
"nested": {
"path": "keywords"
},
"aggs": {
"keyword_name": {
"terms": {
"field": "keywords.keyword"
},
"aggs": {
"sums": {
"sum": {
"field": "keywords.count"
}
}
}
}
}
}
}
}
result:
"buckets": [{
"key": "value1",
"doc_count": 495,
"sums": {
"value": 609
}
},
{
"key": "value2",
"doc_count": 440,
"sums": {
"value": 615
}
},
{
"key": "value3",
"doc_count": 319,
"sums": {
"value": 421
}
},
...]

Elasticsearch: sort by value and dynamic templates

I need sorting for the documents like :
{
customer: {
fullname: "Lorem ipsum"
},
order_number: "12313131",
company: {
name: "Test Inc."
},
date: "10.06.2015 18:00"
}
But as far as I unterstood I can not sort by values in analysed fields. There I am trying to create a mapping :
{
"mappings": {
"_default_": {
"dynamic_templates": [
{
"base": {
"match": "*",
"mapping": {
"type": "multi_field",
"fields": {
"{name}": {"type": "string"},
"_sort": {"type": "string", "analyzer": "sort"}
}
}
}
}
]
}
},
"settings": {
"analysis": {
"analyzer": {
"sort": {
"type": "custom",
"tokenizer": "keyword",
"filter": "lowercase"
}
}
}
}
}
But if I put this configuration, I am getting an exception : ElasticsearchIllegalArgumentException: unknown property. Without this mapping my indexing works fine.
What i want to do is create a multifield called name_sort (not_analysed) so I can sort by values.
****
At leas I can able to create a mapping correctly. My mapping looks like:
{
"muhamo": {
"mappings": {
"bookings": {
"dynamic_templates": [
{
"base": {
"mapping": {
"index": "analyzed",
"type": "{dynamic_type}",
"fields": {
"{name}_sort": {
"index": "not_analyzed",
"type": "{dynamic_type}"
}
}
},
"match": "*",
"match_mapping_type": "string"
}
},
{
"catch_all": {
"mapping": {
"fields": {
"{name}_sort": {
"index": "not_analyzed",
"type": "{dynamic_type}"
}
}
},
"match": "*",
"match_mapping_type": "*"
}
}
],
"properties": {
"bookingType": {
"type": "string",
"fields": {
"bookingType_sort": {
"type": "string",
"index": "not_analyzed"
}
}
},
"comment": {
"type": "string",
"fields": {
"comment_sort": {
"type": "string",
"index": "not_analyzed"
}
}
},
"costLocation": {
"type": "string",
"fields": {
"costLocation_sort": {
"type": "string",
"index": "not_analyzed"
}
}
},
"customer": {
"properties": {
"fullname": {
"type": "string",
"fields": {
"fullname_sort": {
"type": "string",
"index": "not_analyzed"
}
}
}
}
},
"date": {
"type": "string",
"fields": {
"date_sort": {
"type": "string",
"index": "not_analyzed"
}
}
},
"deleted": {
"type": "boolean"
},
"toAirport": {
"type": "boolean"
}
}
}
}
}
}
But if I try to sort my results by customer.fullname_sort I am getting an exception as
query[ConstantScore(*:*)],from[-1],size[-1]: Parse Failure [No mapping found for [customer.fullname_sort] in order to sort on]
You should sort on customer.fullname.fullname_sort. That's the path to your field, according to the mapping of the index.

Elasticsearch: Multi-level nested query not working

My mapping is as follows:
{
"mappings": {
"person": {
"properties": {
"lastUpdated": {
"type": "long"
},
"isDeleted": {
"type": "boolean"
},
"person": {
"properties": {
"car": {
"type": "nested",
"properties": {
"model": {
"type": "string"
},
"make": {
"type": "string"
}
}
},
"last_name": {
"type": "string"
},
"first_name": {
"type": "string"
}
}
}
}
}
}
}
I have two documents:
{
"person": {
"first_name": "Bob",
"last_name": "Doe",
"car": [
{
"make": "Saturn",
"model": "Imprezza"
},
{
"make": "Honda",
"model": "Accord"
}
]
},
"isDeleted": false,
"lastUpdated": 1433257051959
}
and
{
"person": {
"first_name": "Zach",
"last_name": "Foobar",
"car": [
{
"make": "Saturn",
"model": "SL"
},
{
"make": "Subaru",
"model": "Imprezza"
}
]
},
"isDeleted": false,
"lastUpdated": 1433257051959
}
I wanted to query the car.make field and so, I wrote the following query:
{
"query": {
"nested": {
"path": "person.person.car",
"query": {
"match": {
"car.make": "Saturn"
}
},
"inner_hits": {}
}
}
}
However, I am not getting anything back results back in return. When I remove the person level object and try to search, then it works. Any idea how to go about doing multi-level nested queries?
EDIT: On the other hand, when I structure my data like this and query then it works.
{
"mappings": {
"person": {
"properties": {
"car": {
"type": "nested",
"properties": {
"model": {
"type": "string"
},
"make": {
"type": "string"
}
}
},
"last_name": {
"type": "string"
},
"first_name": {
"type": "string"
}
}
}
}
}
{
"first_name": "Zach",
"last_name": "Foobar",
"car": [
{
"make": "Saturn",
"model": "SL"
},
{
"make": "Subaru",
"model": "Imprezza"
}
]
}
{
"first_name": "Bob",
"last_name": "Doe",
"car": [
{
"make": "Saturn",
"model": "Imprezza"
},
{
"make": "Honda",
"model": "Accord"
}
]
}
{
"query": {
"nested": {
"path": "person.car",
"query": {
"match": {
"car.make": "Honda"
}
},
"inner_hits": {}
}
}
}
This way the query works. I feel like this has something to do with multi-level nesting. Multi-level nesting is not working.
The nested path attribute needs to be "person.car".
Add "type": "nested", above the (2nd level) person properties line if you wish person to be a nested field type, which is required for Nested Query searches. The default field type is object field.
The naming you are using is confusing, try to rename your mapping not to use person twice.
{
"query": {
"nested": {
"path": "person.car",
"query": {
"match": {
"make": "Saturn"
}
},
"inner_hits": {}
}
}
}

Categories

Resources