(clarification copied from a comment)
I have a java.util.Map
that has different key value pairs, and some of the values are dates, some numbers, some are strings, and some are also java.util.Map
s that can also contain all kinds of above mentioned types. I am able to put it into the index, I see that the elasticsearch mapping is created automatically with correct field types, now I want to retrieve that Map
and see dates, numbers, strings and nested Map
s instead of what I currently have - just strings and Maps
Further story:
I'm putting a java.util.Map
in Elasticsearch using the following code:
public void putMap(String key, Map<String, ?> value) {
try {
IndexRequest ir = Requests.indexRequest(_index)
.id(key)
.type("doc")
.source(value);
Factory.DB.index(ir); // the high level rest client here
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
I am not able to create mappings explicitly as per my task.
For one of my indices it has created the mapping like this, which is quite fine:
{
"rex": {
"mappings": {
"doc": {
"properties": {
"variables": {
"properties": {
"customer": {
"properties": {
"accounts": {
"properties": {
"dateOpen": {
"type": "date"
},
"id": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
},
"dateOfBirth": {
"type": "date"
},
"firstName": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"id": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"lastName": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"middleName": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}
}
}
}
}
}
}
}
Now I am retrieving my structure back with the following code,
public Map<String, ?> getMap(String key) {
try {
GetRequest gr = new GetRequest(_index, "doc", key);
try {
GetResponse response = Factory.DB.get(gr);
if (!response.isExists()) {
return null;
}
Map<String, ?> ret = response.getSourceAsMap();
return ret;
} catch (ElasticsearchStatusException ee) {
if (ee.status().getStatus() == RestStatus.NOT_FOUND.getStatus()) {
return null;
} else {
throw new RuntimeException(ee);
}
}
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
The dates are returned as strings like "1957-04-29T00:00:00.000Z"
There's no Java object to map this document to as I have only Maps of Maps/Lists/values.
How do I make the Java Rest Client respect the mapping the Elasticsearch created for the index? response.getFields()
returns empty map.
In case it is impossible (like 'source is json/strings by design' etc etc), I am ready to retrieve the mapping in the most convenient form possible and walk through the result by myself. The code to retrieve elasticsearch mapping will be appreciated.
Big thank you!
If you still want to fetch the type mapping and do the conversion manually, the Indices API has a Get Mapping command you can invoke with the Java Low Level REST Client.
String getMapping(RestHighLevelClient client, String index, String type) throws IOException {
String endpoint = index + "/_mapping/" + type;
Response response = client.getLowLevelClient().performRequest("GET", endpoint);
return EntityUtils.toString(response.getEntity());
}
But really I would recommend instead using something like Jackson for data binding. Bind the Map
you get from Elasticsearch to a Java object that models the document, and let Jackson handle the type conversion for you.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With