package com.produban.openbus.storm_ES;
import java.io.IOException;
import java.util.Map;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder;
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsResponse;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import backtype.storm.task.OutputCollector;
import backtype.storm.task.TopologyContext;
import backtype.storm.topology.OutputFieldsDeclarer;
import backtype.storm.topology.base.BaseRichBolt;
import backtype.storm.tuple.Tuple;
import static org.elasticsearch.node.NodeBuilder.*;
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
@SuppressWarnings("serial")
/**
* Abstract <code>IRichBolt</code> implementation capable of indexing data from tuples.
* Tuples are mapped into documents via a <code>TupleMapper</code>.
*
* The bolt expects the following in the StormConfig:
* elastic.search.cluster (ES cluster name)
* elastic.search.host (ES host)
* elastic.search.port (ES port)
*
* Also, the bolt supports a local mode, which is handy for testing. Setting the following
* config to <code>true</code> will cause the bolt to start a local elastic search.
*
* @author boneill42
* @author ptgoetz
*
*/public class ElasticSearchBolt extends BaseRichBolt {
public static final String ELASTIC_LOCAL_MODE = "localMode";
private static final Logger LOG = LoggerFactory.getLogger(ElasticSearchBolt.class);
private OutputCollector collector;
private Client client;
protected TupleMapper tupleMapper;
public ElasticSearchBolt(TupleMapper tupleMapper) {
this.tupleMapper = tupleMapper;
}
@Override
@SuppressWarnings("rawtypes")
public void prepare(Map stormConf, TopologyContext context, OutputCollector collector) {
this.collector = collector;
String elasticSearchHost = (String) stormConf.get(StormElasticSearchConstants.ES_HOST);
Integer elasticSearchPort = ((Long) stormConf.get(StormElasticSearchConstants.ES_PORT)).intValue();
String elasticSearchCluster = (String) stormConf.get(StormElasticSearchConstants.ES_CLUSTER_NAME);
Boolean localMode = (Boolean) stormConf.get(ELASTIC_LOCAL_MODE);
if (localMode != null && localMode) {
client = nodeBuilder().local(true).node().client();
} else {
Settings settings = ImmutableSettings.settingsBuilder().put("cluster.name", elasticSearchCluster).build();
client = new TransportClient(settings).addTransportAddress(new InetSocketTransportAddress(
elasticSearchHost, elasticSearchPort));
// SI existe el indice lo borramos
IndicesExistsResponse res = client.admin().indices().prepareExists("indiceprueba").execute().actionGet();
if (res.isExists()) {
client.admin().indices().prepareDelete("indiceprueba").
execute().actionGet();
}
// MAPPING GOES HERE
//Crear el mapping
/* XContentBuilder mappingBuilder;
try {
mappingBuilder = jsonBuilder().startObject()
.startObject("typeprueba")
.startObject("properties")
.startObject("id")
.field("type", "string")
.field("index", "not_analyzed")
.endObject()
.startObject("MSGID")
.field("type", "string")
.field("index", "not_analyzed")
.endObject()
.startObject("DSN")
.field("type", "string")
.field("index", "not_analyzed")
.endObject()
.startObject("tamano")
.field("type", "long")
.endObject()
.endObject()
.endObject()
.endObject();
System.out.println(mappingBuilder.string());
final CreateIndexRequestBuilder createIndexRequestBuilder = client.admin().indices().prepareCreate("indiceprueba");
createIndexRequestBuilder.addMapping("typeprueba", mappingBuilder);
// MAPPING DONE
createIndexRequestBuilder.execute().actionGet();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} */
}
}
@Override
public void execute(Tuple tuple) {
String id = null;
String indexName = null;
String type = null;
String document = null;
try {
id = this.tupleMapper.mapToId(tuple);
indexName = this.tupleMapper.mapToIndex(tuple);
type = this.tupleMapper.mapToType(tuple);
document = this.tupleMapper.mapToDocument(tuple);
byte[] byteBuffer = document.getBytes();
IndexResponse response;
if(id!=null && !id.equals("")){
response = this.client.prepareIndex(indexName, type, id).setSource(byteBuffer).execute()
.actionGet();
}else{
//No hay indice definido
response = this.client.prepareIndex(indexName, type).setSource(byteBuffer).execute()
.actionGet();
}
LOG.debug("Indexed Document[ " + id + "], Type[" + type + "], Index[" + indexName + "], Version ["
+ response.getVersion() + "]");
collector.ack(tuple);
} catch (Exception e) {
LOG.error("Unable to index Document[ " + id + "], Type[" + type + "], Index[" + indexName + "]", e);
collector.ack(tuple);
}
}
@Override
public void declareOutputFields(OutputFieldsDeclarer declarer) {
// Not generating any output from this bolt.
}
}