Search code examples
javajsonelasticsearchelasticsearch-jest

Using Jest or Java API is there a way to tell Elasticsearch to create documents from json as a String?


Given this POJO:

public class People {
  String sex;
  long age;
  String names;
}

The "names" property will be a json string for which I need to create nested documents for. Here is an example of an instance I need to save to Elasticsearch using Jest Client:

People people = new People();
people.setSex("Male");
people.setAge(21);
people.setNames("[{\"fname\": \"Bob\",\"lname\": \"Smith\"},[{\"fname\": \"Mike\",\"lname\": \"Johnson\"}");

Index index = new Index.Builder(people).index("indexName").type("aType").build();
jestClient.execute(index);

The result document in ES looks like:

"_source" : {
  "sex" : "Male",
  "age" : 21,
  "names" : "[{\"fname\": \"Bob\",\"lname\": \"Smith\"},{\"fname\": \"Mike\",\"lname\": \"Johnson\"}]"
}

So it took the String names and inserted it as a literal String, which makes sense but I actually need to create documents from each name object. In other words I want it to look like this:

"_source" : {
  "sex" : "Male",
  "age" : 21,
  "names" : [{
    "fname": "Bob",
    "lname": "Smith"
   }, {
    "fname": "Mike",
    "lname": "Johnson"
  }]
}

I tried adding a mapping to tell ES to treat it as "nested" but then I get a Mapper Parsing Exception saying "tried to parse field [names] as object, but found a concrete value".

I know I should be able to do this if I create an actual Name POJO object and have a list of them, but unfortunately due to requirements I am unable to do this. I have to use the string of JSON provided in the format specified above.

SOLUTION:

Thanks to Vishal Rao for pointing me in the right direction.

The solution was to change the "names" type to a JsonArray (Google GSON). Then used the Google GSON parser as such:

People people = new People();
people.setSex("Male");
people.setAge(21);

String json = "[{\"fname\": \"Bob\",\"lname\": \"Smith\"},[{\"fname\": \"Mike\",\"lname\": \"Johnson\"}"
JsonParser jsonParser = new JsonParser();
JsonElement jsonElement = jsonParser.parse(json);
JsonArray jsonArray = jsonElement.getAsJsonArray();
people.setNames(jsonArray);

Index index = new Index.Builder(people).index("indexName").type("aType").build();
jestClient.execute(index); 

In addition I also have a mapping that sets the names property to a nested type.


Solution

  • You might want to try converting your string to a JSON object first, that's probably why you're getting that error. Elasticsearch tries to parse it as an object but finds a string there instead. Maybe do something like:

    JSONObject jsonObj = new JSONObject(names);
    

    and then using that object.