Reputation: 12171
I am running this code to return matches
public ArrayList<InnerText> suggest(String text, boolean isPersonal){
TransportClient transportClient = new TransportClient();
Client ESclient = transportClient.addTransportAddress(new InetSocketTransportAddress("localhost", 9300));
OrientGraph graph = new OrientGraph(ConnectionStrings.dbConnection);
Map<String, Object> template_params = new HashMap<>();
template_params.put("innerText", text);
SearchResponse response = ESclient.prepareSearch()
.setTemplateName("innerText_match")
.setTemplateType(ScriptService.ScriptType.FILE)
.setTemplateParams(template_params)
.execute()
.actionGet();
int index = 0;
ArrayList<InnerText> list = new ArrayList<InnerText>();
for (SearchHit hit : response.getHits()) {
//String uuid = hit.field(InnerTextProps.uuid).toString();
//InnerText innerText = vertexToInnerText(graph.getVertexByKey("InnerText.uuid",uuid),false);
//list.add(null);
//hit fields map is org.elasticsearch.util.collect.EmptyImmutableMap
}
return list;
}
and I am getting hits back but the fields map for each of the SearchHits is empty (org.elasticsearch.util.collect.EmptyImmutableMap).Hits have correct id and type though. When using Sense plugin I see that things are stored and retrieved properly with the same query. What am I doing wrong?
Thanks!
Upvotes: 5
Views: 3869
Reputation: 2942
After some exploration of the different methods, I have found that:
SearchHit.sourceAsMap()
will give you access to the data if no specific fields were requestedSearchHit.getFields()
will give you access to the specific fields that were requested in your query using SearchResponse.addFieldDataField( String )
When the entire source is requested (as is the default) the Map
object will contain either String
values or subsequent Map
values:
Map<String,Object> contents = hit.sourceAsMap();
for ( String name : contents.keySet() )
{
Object value = contents.get(name);
System.out.println( "Hit field: "+name+ " object: "+value.getClass().getName() );
if ( contents.get(name) instanceof java.util.HashMap )
{
// Handle map object
}
else
{
// Handle string value
}
}
Obviously when you request specific fields you can handle those using the SearchHit
and SearchHitField
APIs which are easier IMHO.
EDIT
After some more exploration, retrieving the values from the SearchHitField
object is not so easy after all:
Map<String,SearchHitField> fields = hit.getFields();
System.out.println( "Hit fields: "+fields.size() );
for ( SearchHitField field : fields.values() )
{
System.out.println( " Hit field: "+field.getName() );
System.out.println( " Value: "+field.getValue() );
}
Will yield only null
for the values in my case. To be continued...
EDIT2: Final Solutions
First, the addFieldDataField()
method only works if you specify raw fields to retrieve. Using analyzed fields will result in the error "Field data loading is forbidden on <fieldname>
".
Secondly when you retrieve fields using addField()
, always specify leaf fields or the query will fail.
SearchResponse.addFieldDataField( <fieldname>.raw )
SearchResponse.addField( <leaffieldname> )
Now you can retrieve that field's content using SearchHitField.getValue()
.
Good luck.
Upvotes: 5