Expected BEGIN_ARRAY but was BEGIN_OBJECT Retrofit Api call fails - java

I'm creating an Android project for school. Now i want to recieve data from this API using retrofit: Edamam. I keep getting the error shown in the title of this question.
Here are my classes:
Api.java
public interface Api {
final String BASE_URL = "API URL";
final String APP_ID = "SECRET ID";
final String APP_KEY = "SECRET KEY";
#GET("search")
Call<Hits> getHits(#Query("q") String keyword, #Query("app_id") String app_id, #Query("app_key") String app_key);}
HitsController.java
public class HitsController {
public void getHits(String keyword) {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(Api.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
Api api = retrofit.create(Api.class);
Call<Hits> call = api.getHits(keyword, Api.APP_ID, Api.APP_KEY);
//the enqueue is async
call.enqueue(new Callback<Hits>() {
#Override
public void onResponse(Call<Hits> call, Response<Hits> response) {
Hits hits = response.body();
Log.d(TAG, "onResponse: " + hits.getCount());
}
#Override
public void onFailure(Call<Hits> call, Throwable t) {
Log.d(TAG, "onFailure: the call failed.");
Log.d(TAG, "onFailure: " + call.request().url().toString());
Log.d(TAG, t.getMessage());
}
});
}
}
JSON preview (Hits with one Hit):
{
"q": "chicken",
"from": 0,
"to": 10,
"params": {
"sane": [],
"q": [
"chicken"
],
"app_key": [
"5b5829870f140360800ce3af3a6b6781"
],
"app_id": [
"0ddbef04"
]
},
"more": true,
"count": 190722,
"hits": [
{
"recipe": {
"uri": "http://www.edamam.com/ontologies/edamam.owl#recipe_7bf4a371c6884d809682a72808da7dc2",
"label": "Teriyaki Chicken",
"image": "https://www.edamam.com/web-img/262/262b4353ca25074178ead2a07cdf7dc1.jpg",
"source": "David Lebovitz",
"url": "http://www.davidlebovitz.com/2012/12/chicken-teriyaki-recipe-japanese-farm-food/",
"shareAs": "http://www.edamam.com/recipe/teriyaki-chicken-7bf4a371c6884d809682a72808da7dc2/chicken",
"yield": 6,
"dietLabels": [
"Low-Carb"
],
"healthLabels": [
"Sugar-Conscious",
"Peanut-Free",
"Tree-Nut-Free",
"Alcohol-Free"
],
"cautions": [],
"ingredientLines": [
"1/2 cup (125ml) mirin",
"1/2 cup (125ml) soy sauce",
"One 2-inch (5cm) piece of fresh ginger, peeled and grated",
"2-pounds (900g) boneless chicken thighs (4-8 thighs, depending on size)"
],
"ingredients": [
{
"text": "1/2 cup (125ml) mirin",
"weight": 122.99850757795392
},
{
"text": "1/2 cup (125ml) soy sauce",
"weight": 134.72774670265568
},
{
"text": "One 2-inch (5cm) piece of fresh ginger, peeled and grated",
"weight": 15
},
{
"text": "2-pounds (900g) boneless chicken thighs (4-8 thighs, depending on size)",
"weight": 907.18474
}
],
"calories": 2253.101981306866,
"totalWeight": 1179.9109942806097,
"totalTime": 0,
"totalNutrients": {
"ENERC_KCAL": {
"label": "Energy",
"quantity": 2253.101981306866,
"unit": "kcal"
},
"FAT": {
"label": "Fat",
"quantity": 151.56383347020517,
"unit": "g"
},
"FASAT": {
"label": "Saturated",
"quantity": 41.169838892692944,
"unit": "g"
},
"FATRN": {
"label": "Trans",
"quantity": 0.7711070290000002,
"unit": "g"
},
"FAMS": {
"label": "Monounsaturated",
"quantity": 63.10028137309835,
"unit": "g"
},
"FAPU": {
"label": "Polyunsaturated",
"quantity": 31.82952890962799,
"unit": "g"
},
"CHOCDF": {
"label": "Carbs",
"quantity": 17.72546514133862,
"unit": "g"
},
"FIBTG": {
"label": "Fiber",
"quantity": 1.3778219736212456,
"unit": "g"
},
"SUGAR": {
"label": "Sugars",
"quantity": 0.7939109868106228,
"unit": "g"
},
"PROCNT": {
"label": "Protein",
"quantity": 161.72175016748596,
"unit": "g"
},
"CHOLE": {
"label": "Cholesterol",
"quantity": 889.0410452000001,
"unit": "mg"
},
"NA": {
"label": "Sodium",
"quantity": 8139.824735928436,
"unit": "mg"
},
"CA": {
"label": "Calcium",
"quantity": 116.51301359077408,
"unit": "mg"
},
"MG": {
"label": "Magnesium",
"quantity": 276.82169621464243,
"unit": "mg"
},
"K": {
"label": "Potassium",
"quantity": 2529.722194651041,
"unit": "mg"
},
"FE": {
"label": "Iron",
"quantity": 8.335407066766463,
"unit": "mg"
},
"ZN": {
"label": "Zinc",
"quantity": 12.950414243828696,
"unit": "mg"
},
"P": {
"label": "Phosphorus",
"quantity": 1660.4080117810859,
"unit": "mg"
},
"VITA_RAE": {
"label": "Vitamin A",
"quantity": 208.65249020000002,
"unit": "µg"
},
"VITC": {
"label": "Vitamin C",
"quantity": 0.75,
"unit": "mg"
},
"THIA": {
"label": "Thiamin (B1)",
"quantity": 0.7104550166118764,
"unit": "mg"
},
"RIBF": {
"label": "Riboflavin (B2)",
"quantity": 1.542818655059382,
"unit": "mg"
},
"NIA": {
"label": "Niacin (B3)",
"quantity": 45.028415542590324,
"unit": "mg"
},
"VITB6A": {
"label": "Vitamin B6",
"quantity": 3.3713281129199304,
"unit": "mg"
},
"FOLDFE": {
"label": "Folate equivalent (total)",
"quantity": 47.7274267383718,
"unit": "µg"
},
"FOLFD": {
"label": "Folate (food)",
"quantity": 47.7274267383718,
"unit": "µg"
},
"VITB12": {
"label": "Vitamin B12",
"quantity": 5.6245453880000005,
"unit": "µg"
},
"VITD": {
"label": "Vitamin D",
"quantity": 0.9071847400000002,
"unit": "µg"
},
"TOCPHA": {
"label": "Vitamin E",
"quantity": 1.944087954,
"unit": "mg"
},
"VITK1": {
"label": "Vitamin K",
"quantity": 19.065879540000005,
"unit": "µg"
}
},
"totalDaily": {
"ENERC_KCAL": {
"label": "Energy",
"quantity": 112.6550990653433,
"unit": "%"
},
"FAT": {
"label": "Fat",
"quantity": 233.17512841570027,
"unit": "%"
},
"FASAT": {
"label": "Saturated",
"quantity": 205.8491944634647,
"unit": "%"
},
"CHOCDF": {
"label": "Carbs",
"quantity": 5.908488380446207,
"unit": "%"
},
"FIBTG": {
"label": "Fiber",
"quantity": 5.511287894484982,
"unit": "%"
},
"PROCNT": {
"label": "Protein",
"quantity": 323.44350033497193,
"unit": "%"
},
"CHOLE": {
"label": "Cholesterol",
"quantity": 296.3470150666667,
"unit": "%"
},
"NA": {
"label": "Sodium",
"quantity": 339.1593639970182,
"unit": "%"
},
"CA": {
"label": "Calcium",
"quantity": 11.651301359077408,
"unit": "%"
},
"MG": {
"label": "Magnesium",
"quantity": 65.90992767015297,
"unit": "%"
},
"K": {
"label": "Potassium",
"quantity": 53.823876481937035,
"unit": "%"
},
"FE": {
"label": "Iron",
"quantity": 46.307817037591455,
"unit": "%"
},
"ZN": {
"label": "Zinc",
"quantity": 117.73103858026087,
"unit": "%"
},
"P": {
"label": "Phosphorus",
"quantity": 237.20114454015513,
"unit": "%"
},
"VITA_RAE": {
"label": "Vitamin A",
"quantity": 23.183610022222226,
"unit": "%"
},
"VITC": {
"label": "Vitamin C",
"quantity": 0.8333333333333334,
"unit": "%"
},
"THIA": {
"label": "Thiamin (B1)",
"quantity": 59.204584717656374,
"unit": "%"
},
"RIBF": {
"label": "Riboflavin (B2)",
"quantity": 118.67835808149093,
"unit": "%"
},
"NIA": {
"label": "Niacin (B3)",
"quantity": 281.4275971411895,
"unit": "%"
},
"VITB6A": {
"label": "Vitamin B6",
"quantity": 259.33293176307154,
"unit": "%"
},
"FOLDFE": {
"label": "Folate equivalent (total)",
"quantity": 11.93185668459295,
"unit": "%"
},
"VITB12": {
"label": "Vitamin B12",
"quantity": 234.35605783333335,
"unit": "%"
},
"VITD": {
"label": "Vitamin D",
"quantity": 6.047898266666667,
"unit": "%"
},
"TOCPHA": {
"label": "Vitamin E",
"quantity": 12.96058636,
"unit": "%"
},
"VITK1": {
"label": "Vitamin K",
"quantity": 15.888232950000004,
"unit": "%"
}
},
"digest": [
{
"label": "Fat",
"tag": "FAT",
"schemaOrgTag": "fatContent",
"total": 151.56383347020517,
"hasRDI": true,
"daily": 233.17512841570027,
"unit": "g",
"sub": [
{
"label": "Saturated",
"tag": "FASAT",
"schemaOrgTag": "saturatedFatContent",
"total": 41.169838892692944,
"hasRDI": true,
"daily": 205.8491944634647,
"unit": "g"
},
{
"label": "Trans",
"tag": "FATRN",
"schemaOrgTag": "transFatContent",
"total": 0.7711070290000002,
"hasRDI": false,
"daily": 0,
"unit": "g"
},
{
"label": "Monounsaturated",
"tag": "FAMS",
"schemaOrgTag": null,
"total": 63.10028137309835,
"hasRDI": false,
"daily": 0,
"unit": "g"
},
{
"label": "Polyunsaturated",
"tag": "FAPU",
"schemaOrgTag": null,
"total": 31.82952890962799,
"hasRDI": false,
"daily": 0,
"unit": "g"
}
]
},
{
"label": "Carbs",
"tag": "CHOCDF",
"schemaOrgTag": "carbohydrateContent",
"total": 17.72546514133862,
"hasRDI": true,
"daily": 5.908488380446207,
"unit": "g",
"sub": [
{
"label": "Carbs (net)",
"tag": "CHOCDF.net",
"schemaOrgTag": null,
"total": 16.347643167717376,
"hasRDI": false,
"daily": 0,
"unit": "g"
},
{
"label": "Fiber",
"tag": "FIBTG",
"schemaOrgTag": "fiberContent",
"total": 1.3778219736212456,
"hasRDI": true,
"daily": 5.511287894484982,
"unit": "g"
},
{
"label": "Sugars",
"tag": "SUGAR",
"schemaOrgTag": "sugarContent",
"total": 0.7939109868106228,
"hasRDI": false,
"daily": 0,
"unit": "g"
},
{
"label": "Sugars, added",
"tag": "SUGAR.added",
"schemaOrgTag": null,
"total": 0,
"hasRDI": false,
"daily": 0,
"unit": "g"
}
]
},
{
"label": "Protein",
"tag": "PROCNT",
"schemaOrgTag": "proteinContent",
"total": 161.72175016748596,
"hasRDI": true,
"daily": 323.44350033497193,
"unit": "g"
},
{
"label": "Cholesterol",
"tag": "CHOLE",
"schemaOrgTag": "cholesterolContent",
"total": 889.0410452000001,
"hasRDI": true,
"daily": 296.3470150666667,
"unit": "mg"
},
{
"label": "Sodium",
"tag": "NA",
"schemaOrgTag": "sodiumContent",
"total": 8139.824735928436,
"hasRDI": true,
"daily": 339.1593639970182,
"unit": "mg"
},
{
"label": "Calcium",
"tag": "CA",
"schemaOrgTag": null,
"total": 116.51301359077408,
"hasRDI": true,
"daily": 11.651301359077408,
"unit": "mg"
},
{
"label": "Magnesium",
"tag": "MG",
"schemaOrgTag": null,
"total": 276.82169621464243,
"hasRDI": true,
"daily": 65.90992767015297,
"unit": "mg"
},
{
"label": "Potassium",
"tag": "K",
"schemaOrgTag": null,
"total": 2529.722194651041,
"hasRDI": true,
"daily": 53.823876481937035,
"unit": "mg"
},
{
"label": "Iron",
"tag": "FE",
"schemaOrgTag": null,
"total": 8.335407066766463,
"hasRDI": true,
"daily": 46.307817037591455,
"unit": "mg"
},
{
"label": "Zinc",
"tag": "ZN",
"schemaOrgTag": null,
"total": 12.950414243828696,
"hasRDI": true,
"daily": 117.73103858026087,
"unit": "mg"
},
{
"label": "Phosphorus",
"tag": "P",
"schemaOrgTag": null,
"total": 1660.4080117810859,
"hasRDI": true,
"daily": 237.20114454015513,
"unit": "mg"
},
{
"label": "Vitamin A",
"tag": "VITA_RAE",
"schemaOrgTag": null,
"total": 208.65249020000002,
"hasRDI": true,
"daily": 23.183610022222226,
"unit": "µg"
},
{
"label": "Vitamin C",
"tag": "VITC",
"schemaOrgTag": null,
"total": 0.75,
"hasRDI": true,
"daily": 0.8333333333333334,
"unit": "mg"
},
{
"label": "Thiamin (B1)",
"tag": "THIA",
"schemaOrgTag": null,
"total": 0.7104550166118764,
"hasRDI": true,
"daily": 59.204584717656374,
"unit": "mg"
},
{
"label": "Riboflavin (B2)",
"tag": "RIBF",
"schemaOrgTag": null,
"total": 1.542818655059382,
"hasRDI": true,
"daily": 118.67835808149093,
"unit": "mg"
},
{
"label": "Niacin (B3)",
"tag": "NIA",
"schemaOrgTag": null,
"total": 45.028415542590324,
"hasRDI": true,
"daily": 281.4275971411895,
"unit": "mg"
},
{
"label": "Vitamin B6",
"tag": "VITB6A",
"schemaOrgTag": null,
"total": 3.3713281129199304,
"hasRDI": true,
"daily": 259.33293176307154,
"unit": "mg"
},
{
"label": "Folate equivalent (total)",
"tag": "FOLDFE",
"schemaOrgTag": null,
"total": 47.7274267383718,
"hasRDI": true,
"daily": 11.93185668459295,
"unit": "µg"
},
{
"label": "Folate (food)",
"tag": "FOLFD",
"schemaOrgTag": null,
"total": 47.7274267383718,
"hasRDI": false,
"daily": 0,
"unit": "µg"
},
{
"label": "Folic acid",
"tag": "FOLAC",
"schemaOrgTag": null,
"total": 0,
"hasRDI": false,
"daily": 0,
"unit": "µg"
},
{
"label": "Vitamin B12",
"tag": "VITB12",
"schemaOrgTag": null,
"total": 5.6245453880000005,
"hasRDI": true,
"daily": 234.35605783333335,
"unit": "µg"
},
{
"label": "Vitamin D",
"tag": "VITD",
"schemaOrgTag": null,
"total": 0.9071847400000002,
"hasRDI": true,
"daily": 6.047898266666667,
"unit": "µg"
},
{
"label": "Vitamin E",
"tag": "TOCPHA",
"schemaOrgTag": null,
"total": 1.944087954,
"hasRDI": true,
"daily": 12.96058636,
"unit": "mg"
},
{
"label": "Vitamin K",
"tag": "VITK1",
"schemaOrgTag": null,
"total": 19.065879540000005,
"hasRDI": true,
"daily": 15.888232950000004,
"unit": "µg"
}
]
},
"bookmarked": false,
"bought": false
},
As you can see a lot of model classes are needed:
preview classes
I am clueless, I went through every other post but can't seem to find an answer for my problem...
I hope that someone is able to help me!
Thanks in advance :)
EDIT: POSTED THE HITS CLASS
public class Hits {
private String q;
private int from;
private int to;
private String[][] params;
private int count;
private boolean more;
private Hit[] hits;
public Hits(String q, int from, int to, String[][] params, int count, boolean more, Hit[] hits) {
this.q = q;
this.from = from;
this.to = to;
this.params = params;
this.count = count;
this.more = more;
this.hits = hits;
}
public String getQ() {
return q;
}
public int getFrom() {
return from;
}
public int getTo() {
return to;
}
public String[][] getParams() {
return params;
}
public int getCount() {
return count;
}
public boolean isMore() {
return more;
}
public Hit[] getHits() {
return hits;
}
}

You need to get configure retrofit to get only a List of Hits, that is List<Hits>
but its much easier if you created a Java bean which will contain the list of Hits inside, just like the Json response its a object that has a array inside.
For example you have a Example class which has a List<Hits> hits inside
public class Example{
#SerializedName("hits")
private List<Hits> hits;
// optionally you can add the other fields also (not mandatory)
// set getters and setters here
and then you need to modify your Retrofit interface to return a Example object which will contain the Hits
#GET("search")
Call<Example> getExample(#Query("q") String keyword, #Query("app_id") String app_id, #Query("app_key") String app_key);}
and the implementation also
Call<Example> call = api.getHits(keyword, Api.APP_ID, Api.APP_KEY);
//the enqueue is async
call.enqueue(new Callback<Hits>() {
#Override
public void onResponse(Call<Example> call, Response<Example> response) {
Hits hits = response.body();
Log.d(TAG, "onResponse: " + response.getHits().size());
}
#Override
public void onFailure(Call<Example> call, Throwable t) {
}
});

Related

JOLT shift transformation: filter by inner value of a property (not the name) - only some properties

I am trying to transform a JSON using Jolt transformation looking for some input here.
I am trying to filter by the inner value of the attribute.
My goal is to get an array that contains only the items with the typeName 'xx'. But not all the item object, only some of the fields
{
"id": "11_1",
"action": "add",
"payment": {
"paied": true,
"coin": "dollar"
},
"type": {
"id": "11_1_xx",
"typeName": "xx"
},
"details": {
"place": {
"id": "123",
"name": "xx"
},
"status": {
"id": "123",
"name": "xx"
}
}
}
Here is my input and expected output:
Input:
{
"id": 11,
"item": [
{
"id": "11_1",
"action": "add",
"payment": {
"paied": true,
"coin": "dollar"
},
"type": {
"id": "11_1_xx",
"typeName": "xx",
"typeGroup": "xx",
"typeValue": "xx"
},
"details": {
"place": {
"id": "123",
"name": "xx"
},
"status": {
"id": "123",
"name": "xx"
},
"reason": {
"id": "123",
"name": "xx"
}
},
"item": [
{
"id": "11_1_1",
"action": "add",
"payment": {
"paied": true,
"coin": "dollar"
},
"type": {
"id": "11_1_1_zz",
"typeName": "zz",
"typeGroup": "zz",
"typeValue": "zz"
},
"details": {
"place": {
"id": "123",
"name": "xx"
},
"status": {
"id": "123",
"name": "xx"
},
"reason": {
"id": "123",
"name": "xx"
}
},
"item": [
{
"id": "11_1_1_1",
"action": "add",
"payment": {
"paied": true,
"coin": "NIS"
},
"type": {
"id": "11_1_1_1_xx",
"typeName": "xx",
"typeGroup": "xx",
"typeValue": "xx"
},
"details": {
"place": {
"id": "123",
"name": "xx"
},
"status": {
"id": "123",
"name": "xx"
},
"reason": {
"id": "123",
"name": "xx"
}
}
}
]
},
{
"id": "11_1_2",
"action": "add",
"payment": {
"paied": false,
"coin": "dollar"
},
"type": {
"id": "11_1_2_xx",
"typeName": "xx",
"typeGroup": "xx",
"typeValue": "xx"
},
"details": {
"place": {
"id": "123",
"name": "xx"
},
"status": {
"id": "123",
"name": "xx"
},
"reason": {
"id": "123",
"name": "xx"
}
},
"item": [
{
"id": "11_1_2_1",
"action": "add",
"payment": {
"paied": false,
"coin": "NIS"
},
"type": {
"id": "11_1_2_1_zz",
"typeName": "zz",
"typeGroup": "zz",
"typeValue": "zz"
},
"details": {
"place": {
"id": "123",
"name": "xx"
},
"status": {
"id": "123",
"name": "xx"
},
"reason": {
"id": "123",
"name": "xx"
}
}
}
]
}
]
}
]
}
Expected output:
[
{
"id": "11_1",
"action": "add",
"payment": {
"paied": true,
"coin": "dollar"
},
"type": {
"id": "11_1_xx",
"typeName": "xx"
},
"details": {
"place": {
"id": "123",
"name": "xx"
},
"status": {
"id": "123",
"name": "xx"
}
}
},
{
"id": "11_1_1_1",
"action": "add",
"payment": {
"paied": true,
"coin": "NIS"
},
"type": {
"id": "11_1_1_1_xx",
"typeName": "xx"
},
"details": {
"place": {
"id": "123",
"name": "xx"
},
"status": {
"id": "123",
"name": "xx"
}
}
},
{
"id": "11_1_2",
"action": "add",
"payment": {
"paied": false,
"coin": "dollar"
},
"type": {
"id": "11_1_2_xx",
"typeName": "xx"
},
"details": {
"place": {
"id": "123",
"name": "xx"
},
"status": {
"id": "123",
"name": "xx"
}
}
}
]
Can you please help me to write a simple spec that will do this?
You can use the following explained spec
[
{
// Determine all key-value pairs partitioned under the main value and type.typeValue combinations
"operation": "shift",
"spec": {
"item": {
"*": {
"item": {
"*": {
"item": {
"*": {
"type": {
"#(1,id)": "#(2,id).#(1,typeName).id", //traverse } character twice in order to reach the main id of the object
"#(1,action)": "#(2,id).#(1,typeName).action",
"*": "#(2,id).#(1,typeName).&1.&" // &1 replicates "type" key, & does the leaf value
},
"*": "#(1,id).#(1,type.typeName).&"
}
},
"type": {
"#(1,id)": "#(2,id).#(1,typeName).id",
"#(1,action)": "#(2,id).#(1,typeName).action",
"*": "#(2,id).#(1,typeName).&1.&"
},
"*": "#(1,id).#(1,type.typeName).&"
}
},
"type": {
"#(1,id)": "#(2,id).#(1,typeName).id",
"#(1,action)": "#(2,id).#(1,typeName).action",
"*": "#(2,id).#(1,typeName).&1.&"
},
"*": "#(1,id).#(1,type.typeName).&"
}
}
}
},
{
// Filter out by the desired value(in this case it's "xx")
"operation": "shift",
"spec": {
"*": {
"xx": ""
}
}
},
{
// Get rid of same repeating components of id and action arrays
"operation": "cardinality",
"spec": {
"*": {
"id": "ONE",
"action": "ONE"
}
}
},
{
// Get rid of undesired attributes
"operation": "remove",
"spec": {
"*": {
"type": {
"typeGroup": "",
"typeValue": ""
},
"det*": {
"reason": ""
}
}
}
}
]
You may try library Josson. Function map() build a new ObjectNode. Function field() modify the current ObjectNode and can be used to remove fields. The transformation statement is short and easy to understand.
https://github.com/octomix/josson
Josson josson = Josson.fromJsonString(inputJSON);
JsonNode node = josson.getNode(
"cumulateCollect(" +
" [type.typeName='xx']" + // filter
" .field(type.map(id, typeName)" + // need "type.id" and "type.typeName"
" ,details.field(reason:)" + // remove "details.reason"
" ,item:)" + // remove "item"
" ,item)"); // next round
System.out.println(node.toPrettyString());

will spring-data-rest expose methods in QueryByExampleExecutor interface?

i just learned how to use spring-data-rest to expose methods in repository. i wonder will the spring-data-rest expose methods in QueryByExampleExecutor<T>interface.if not, is there anyway to expose those methods. thx :).
i have a repository class that extend JpaRepository and i did not find any Restful api like methods in QueryByExampleExecutor<T> with resource discovery api.
this is what i got from resource discovery api
{
"alps": {
"version": "1.0",
"descriptor": [
{
"id": "studentEntity-representation",
"href": "http://127.0.0.1:8080/data/profile/studentEntities",
"descriptor": [
{
"name": "name",
"type": "SEMANTIC"
},
{
"name": "age",
"type": "SEMANTIC"
},
{
"name": "height",
"type": "SEMANTIC"
},
{
"name": "weight",
"type": "SEMANTIC"
},
{
"name": "hasPassed",
"type": "SEMANTIC"
}
]
},
{
"id": "create-studentEntities",
"name": "studentEntities",
"type": "UNSAFE",
"descriptor": [],
"rt": "#studentEntity-representation"
},
{
"id": "get-studentEntities",
"name": "studentEntities",
"type": "SAFE",
"descriptor": [
{
"name": "page",
"type": "SEMANTIC",
"doc": {
"format": "TEXT",
"value": "The page to return."
}
},
{
"name": "size",
"type": "SEMANTIC",
"doc": {
"format": "TEXT",
"value": "The size of the page to return."
}
},
{
"name": "sort",
"type": "SEMANTIC",
"doc": {
"format": "TEXT",
"value": "The sorting criteria to use to calculate the content of the page."
}
}
],
"rt": "#studentEntity-representation"
},
{
"id": "delete-studentEntity",
"name": "studentEntity",
"type": "IDEMPOTENT",
"descriptor": [],
"rt": "#studentEntity-representation"
},
{
"id": "update-studentEntity",
"name": "studentEntity",
"type": "IDEMPOTENT",
"descriptor": [],
"rt": "#studentEntity-representation"
},
{
"id": "get-studentEntity",
"name": "studentEntity",
"type": "SAFE",
"descriptor": [],
"rt": "#studentEntity-representation"
},
{
"id": "patch-studentEntity",
"name": "studentEntity",
"type": "UNSAFE",
"descriptor": [],
"rt": "#studentEntity-representation"
}
]
}
}

Elasticsearch High Level Rest Client Java sorting not working properly

I am pretty new with Elasticsearch High Level Rest Client (Java).
I have a very simple query which lists all records, but it seems sorting is not working properly.
Some of the fields are text types, so I needed to set fielddata to true.
Update:
Thanks Andrei for the solution.
I need to add another field which is an array of objects user.groups
I added .keyword to the mapping fields (text) which are sortable.
But I am getting unexpected results.
Example:
...
"groups": [
{"name", "ECPay", ... },
{"name", "Abangers", ... }
]
...
Based from the output (below), if there are two group items ECPay and Abangers... using user.groups.name.keyword sorting will consider Abangers.
I would like to consider the first element of user.groups array as a basis of the sort.
Based from the example (above), tt will base the sort with ECPay since it is the first element of the array.
To understand the problem (updated), let us check the search result (sort) below.
Search Result (Output):
{
"took": 18,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 74,
"max_score": null,
"hits": [
{
"_index": "acme_users",
"_type": "user",
"_id": "5",
"_score": null,
"_source": {
"name": "Ericsson Joseph Sultan Atutuli",
"country": "",
"uuid": "5",
"userId": 5,
"email": "ejsultanatutuli#gmail.com",
"deletedInd": false,
"groups": [
{
"name": "ECPay",
"id": 2
},
{
"name": "Abangers",
"id": 4
}
],
"company": ""
},
"sort": [
"Abangers"
]
},
{
"_index": "acme_users",
"_type": "user",
"_id": "54",
"_score": null,
"_source": {
"name": "Florentina Atutuli",
"country": null,
"uuid": "54",
"userId": 54,
"email": "florentina.atutuli#gmail.com",
"deletedInd": false,
"groups": [
{
"name": "Abangers",
"id": 4
},
{
"name": "Test Group",
"id": 5
}
],
"company": null
},
"sort": [
"Abangers"
]
},
{
"_index": "acme_users",
"_type": "user",
"_id": "37",
"_score": null,
"_source": {
"name": "dsfsdfsdf",
"country": null,
"uuid": "37",
"userId": 37,
"email": "asdf#sdf.com",
"deletedInd": false,
"groups": [
{
"name": "Abangers",
"id": 4
},
{
"name": "Test Group",
"id": 5
}
],
"company": null
},
"sort": [
"Abangers"
]
},
{
"_index": "acme_users",
"_type": "user",
"_id": "3",
"_score": null,
"_source": {
"name": "Erick Atutuli",
"country": "Philippines",
"email": "erickatutuli#pakyas.com",
"userId": 3,
"uuid": "d8f4ab43-d33e-4a82-a08b-eb73342a0546",
"groups": [
{
"name": "ECPay",
"id": 2
},
{
"name": "Abangers",
"id": 4
}
],
"deletedInd": false,
"company": "Hotlegs Incorporated"
},
"sort": [
"Abangers"
]
},
{
"_index": "acme_users",
"_type": "user",
"_id": "34",
"_score": null,
"_source": {
"name": "Chun-Li",
"country": null,
"email": "chunli#pakyas.com",
"uuid": "34",
"userId": 34,
"deletedInd": false,
"groups": [
{
"name": "Customers AU",
"id": 1
}
],
"company": null
},
"sort": [
"Customers AU"
]
},
{
"_index": "acme_users",
"_type": "user",
"_id": "57",
"_score": null,
"_source": {
"name": "Eddy Bear",
"country": "US",
"email": "eddybear#pakyas.com",
"uuid": "57",
"userId": 57,
"deletedInd": false,
"groups": [
{
"name": "Customers AU",
"id": 1
}
],
"company": "Jollibee"
},
"sort": [
"Customers AU"
]
},
{
"_index": "acme_users",
"_type": "user",
"_id": "42",
"_score": null,
"_source": {
"name": "Alfredo Pitik Mingaw",
"country": "",
"email": "akomykel#gmail.com",
"userId": 42,
"uuid": "42",
"deletedInd": false,
"groups": [
{
"name": "ECPay",
"id": 2
}
],
"company": ""
},
"sort": [
"ECPay"
]
},
{
"_index": "acme_users",
"_type": "user",
"_id": "20",
"_score": null,
"_source": {
"name": "test",
"country": "Åland Islands",
"userId": 20,
"email": "test102#email.com",
"uuid": "20",
"groups": [
{
"name": "ECPay",
"id": 2
}
],
"deletedInd": false,
"company": "test"
},
"sort": [
"ECPay"
]
},
...
]
}
}
Now I added keyword field in the user mapping:
...
"groups": {
"properties": {
"name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
},
...
Make text fields sortable, removed fielddata and added keywords
http://localhost:9200/acme_users/_mapping/user
{
"properties": {
"name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"company": {
"type": "text",
"fielddata": true
},
"country": {
"type": "text",
"fielddata": true
},
"groups": {
"properties": {
"name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
},
"email": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}
The query below is generated from my Java application (Spring).
This is a very simple case wherein I just sort the results into name ascending order.
Query
Added .keyword to the sorting field. In the sample below... it will sort using groups.name.keyword which was originally groups.name
http://localhost:9200/acme_users/user/_search
{
"from" : 0,
"size" : 15,
"query" : {
"match_all" : {
"boost" : 1.0
}
},
"sort" : [
{
"groups.name.keyword" : {
"order" : "asc"
}
}
]
}
Original Problem:
But my problem now is, it seems ES sort does not work properly. The results changes when I change the order from asc to desc (vice versa).
Though the results changes, it seems that the names (result) is not sorting properly (a-z) or (z-a).
Seems that it is getting the last part of name and using it as the basis for the sort. I would like to base it on the first character value of name.
Original Search Result:
{
"took": 4,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 73,
"max_score": null,
"hits": [
{
"_index": "acme_users",
"_type": "user",
"_id": "22",
"_score": null,
"_source": {
"name": "Popeye Partner 01",
"country": null,
"userId": 22,
"email": "popeye_partner_01#kugmo.com",
"uuid": "22",
"deletedInd": false,
"company": null
},
"sort": [
"01"
]
},
{
"_index": "acme_users",
"_type": "user",
"_id": "24",
"_score": null,
"_source": {
"name": "Dummy User 01",
"country": null,
"userId": 24,
"email": "dummy#dummy.com",
"uuid": "24",
"deletedInd": false,
"company": null
},
"sort": [
"01"
]
},
{
"_index": "acme_users",
"_type": "user",
"_id": "23",
"_score": null,
"_source": {
"name": "Popeye Partner 02",
"country": null,
"userId": 23,
"email": "popeye_partner_02#kugmo.com",
"uuid": "23",
"deletedInd": false,
"company": null
},
"sort": [
"02"
]
},
{
"_index": "acme_users",
"_type": "user",
"_id": "25",
"_score": null,
"_source": {
"name": "RT Administrator",
"country": null,
"userId": 25,
"email": "rt_administrator#kugmo.com",
"uuid": "25",
"deletedInd": false,
"company": null
},
"sort": [
"administrator"
]
},
{
"_index": "acme_users",
"_type": "user",
"_id": "48",
"_score": null,
"_source": {
"name": "John Patrick Abnoy",
"country": null,
"userId": 48,
"email": "patrickabnoy#gmail.com",
"uuid": "48",
"deletedInd": false,
"company": null
},
"sort": [
"abnoy"
]
},
{
"_index": "acme_users",
"_type": "user",
"_id": "5",
"_score": null,
"_source": {
"name": "Ericsson John Santol Atutuli",
"country": "",
"uuid": "5",
"userId": 5,
"email": "ejsantolatutuli#gmail.com",
"deletedInd": false,
"company": ""
},
"sort": [
"atutuli"
]
},
{
"_index": "acme_users",
"_type": "user",
"_id": "54",
"_score": null,
"_source": {
"name": "Florentina Atutuli",
"country": null,
"uuid": "54",
"userId": 54,
"email": "florentina.atutuli#gmail.com",
"deletedInd": false,
"company": null
},
"sort": [
"atutuli"
]
},
{
"_index": "acme_users",
"_type": "user",
"_id": "49",
"_score": null,
"_source": {
"name": "Laarnie Santol Atutuli",
"country": "",
"email": "lmsantolatutuli#gmail.com",
"userId": 49,
"uuid": "49",
"deletedInd": false,
"company": ""
},
"sort": [
"atutuli"
]
},
{
"_index": "acme_users",
"_type": "user",
"_id": "3",
"_score": null,
"_source": {
"name": "Eric Atutuli",
"country": "Philippines",
"uuid": "d8f4ab43-d33e-4a82-a08b-eb73342a0546",
"userId": 3,
"email": "ericatutuli#kugmo.com",
"deletedInd": false,
"company": "Hotlegs Incorporated"
},
"sort": [
"atutuli"
]
},
{
"_index": "acme_users",
"_type": "user",
"_id": "29",
"_score": null,
"_source": {
"name": "Auberto Matulis",
"country": null,
"userId": 29,
"email": "bert.matulis#gmail.com",
"uuid": "29",
"deletedInd": false,
"company": null
},
"sort": [
"auberto"
]
}
]
}
}
Thanks!
name is a text field which means it is analyzed. Analyzed means it's split into tokens. If Popeye Partner 01 is split into popeye, partner, 01 which field you want to use for sorting? Probably none of them, since you want the sort to happen on the original text. For this to happen, add a sub-field to your name field
{
"name": {
"type" "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
and make it keyword then in your query use that for sorting:
"sort" : [
{
"name.keyword" : {
"order" : "asc"
}
}
]
We ran into the same issue and then we looked at the mapping which we created at the time of indexCreation and we observed a couple of things.
All the fields which always have one word as the value should be changed to keyword so we dont need to append .keyword in all the fields names(dont want to mantain schema on client side to append .keyword) or add "fielddata": true( avoid this as much as possible, because it takes up your heap mem)
"type":"keyword"
All the values which are defined as text but actually they are number, so we changed to either long or scaled_float. This helped us in sorting and aggregation.
"type":"long"
OR
"type": "scaled_float",
"scaling_factor": 100

Highly nested json data

I have three JSON arrays named item, topping and batter.
Now I want to store this data into single json object. It is highly nested data I don't know how to store data into single object like this.
Resultant object should be like this:
{
"item": [{
"id": "0001",
"type": "donut",
"name": "Cake",
"ppu": 0.55,
"batter": [{
"id": "1001",
"type": "Regular"
},
{
"id": "1002",
"type": "Chocolate"
},
{
"id": "1003",
"type": "Blueberry"
},
{
"id": "1004",
"type": "Devil's Food"
}
],
"topping": [{
"id": "5001",
"type": "None"
},
{
"id": "5002",
"type": "Glazed"
},
{
"id": "5005",
"type": "Sugar"
},
{
"id": "5007",
"type": "Powdered Sugar"
},
{
"id": "5006",
"type": "Chocolate with Sprinkles"
},
{
"id": "5003",
"type": "Chocolate"
},
{
"id": "5004",
"type": "Maple"
}
]
},
{
"id": "0002",
"type": "donut",
"name": "Raised",
"ppu": 0.55,
"batter": [{
"id": "1001",
"type": "Regular"
}],
"topping": [{
"id": "5001",
"type": "None"
},
{
"id": "5002",
"type": "Glazed"
},
{
"id": "5005",
"type": "Sugar"
},
{
"id": "5003",
"type": "Chocolate"
},
{
"id": "5004",
"type": "Maple"
}
]
},
{
"id": "0003",
"type": "donut",
"name": "Old Fashioned",
"ppu": 0.55,
"batter": [{
"id": "1001",
"type": "Regular"
},
{
"id": "1002",
"type": "Chocolate"
}
],
"topping": [{
"id": "5001",
"type": "None"
},
{
"id": "5002",
"type": "Glazed"
},
{
"id": "5003",
"type": "Chocolate"
},
{
"id": "5004",
"type": "Maple"
}
]
}
]
}

How can I extract the array of hashmap object from a hashmap object?

{
"errorCode": 200,
"opMessage": {
"personalDetails": {
"dob": {
"mm": 2,
"dd": 2,
"yyyy": 1975
},
"name": {
"fname": "sai gampa",
"lName": "krishna"
},
"maritalStatus": "Single",
"ssn": "123-45-7777"
},
"id": "0101",
"contactDetails": {
"address": [
{
"isPrimary": true,
"id": "HOME;2017-06-30",
"type": "Home",
"addr": {
"country": "USA",
"addr2": "W 24th St",
"addr1": "518",
"city": "New York",
"postalCode": "11122",
"state": "NY"
}
},
{
"isPrimary": false,
"id": "BUSN;2017-07-04",
"type": "Work",
"addr": {
"country": "USA",
"addr2": "Agsuaiajs",
"addr1": "Qwertyy",
"city": "Shshshsjsj",
"postalCode": "71899",
"state": "CO"
}
}
],
"bestWayToContact": "Phone",
"ph": [
{
"isPrimary": false,
"num": "666-666-6666",
"id": "Work",
"type": "Work"
},
{
"isPrimary": false,
"num": "444-444-4444",
"id": "Cell",
"type": "Cell"
},
{
"isPrimary": true,
"num": "111-111-1111",
"id": "Home",
"type": "Home"
}
],
"eMail": [
{
"isPrimary": true,
"id": "HOME",
"addr": "Shyam#gmail.con"
}
]
}
}
}
HashMap has a method called entrySet(). With entrySet() you can get all the entries in the hashmap.

Categories