使用java操作Elasticsearch创建自定义索引
ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。 我们最熟悉的百度搜索便是应用了Elasticsea..
ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。
我们最熟悉的百度搜索便是应用了Elasticsearch,es提供了高亮、聚合统计、分组查询等。它在分布式部署下提供了强大的索引能力,使其具有极强的实时性,大量应用于项目开发中各种实时的应用场景。它有以下优点:
1.分布式文件存储,而且把每个字段编入索引,使其查询高效速度快
2.扩展性强,便于横向扩展,可处理PB级数据
3.利用其分片和master选举,使其具有较强的容错机制
简单说下linux下部署es集群:
一般只要修改config下的elasticsearch.yml配置文件即可
# https://www.elastic.co/guide/en/elasticsearch/reference/index.html
#
# ---------------------------------- Cluster -----------------------------------
#
# Use a descriptive name for your cluster:
#
#cluster.name: my-application
cluster.name: cluster1
# ------------------------------------ Node ------------------------------------
#
# Use a descriptive name for the node:
#
#node.name: node-1
node.name: node1
# Add custom attributes to the node:
#
#node.attr.rack: r1
#
# ----------------------------------- Paths ------------------------------------
#
# Path to directory where to store the data (separate multiple locations by comma):
#
#path.data: /path/to/data
path.data: /data/es/data
# Path to log files:
#
#path.logs: /path/to/logs
path.logs: /data/es/logs
# ----------------------------------- Memory -----------------------------------
#
# Lock the memory on startup:
#
#bootstrap.memory_lock: true
bootstrap.memory_lock: true
# Make sure that the heap size is set to about half the memory available
# on the system and that the owner of the process is allowed to use this
# limit.
#
# Elasticsearch performs poorly when the system is swapping the memory.
#
# ---------------------------------- Network -----------------------------------
#
# Set the bind address to a specific IP (IPv4 or IPv6):
#
#network.host: 192.168.0.1
network.host: 0.0.0.0
# Set a custom port for HTTP:
#
#http.port: 9200
#
# For more information, consult the network module documentation.
#
# --------------------------------- Discovery ----------------------------------
#
# Pass an initial list of hosts to perform discovery when new node is started:
# The default list of hosts is ["127.0.0.1", "[::1]"]
#
#discovery.zen.ping.unicast.hosts: ["host1", "host2"]
discovery.zen.ping.unicast.hosts: [ "192.168.xx.xxx", "192.168.xx.xxx", "192.168.xx.xxx"]
cluster.name: 集群名称,每个es节点必须拥有相同的集群名称
node.name:节点名称
network.host:节点所在服务器的ip地址,如果要在浏览器直接访问该节点可改为0.0.0.0
http.port:服务端端口,默认9200
discovery.zen.ping.unicast.hosts:集群内所有节点,可用ip也可用节点名称
如果需要增加jvm的内存,可修改config下的jvm.options
接下来重点讲解java中如何连接elasticsearch集群和创建索引及type,且自定义它的结构,本文不会展示全部代码,因为代码量多,主要讲解一个封装思路,后面讲到springboot我会把代码发布到gitHub
创建一个ElasticsearchServiceImpl实现类
1.启动初始化es
@PostConstruct //改注解为启动服务便初始化运行该方法
private void init() {
getHosts(); //加入所有节点
if (connectWhenStartup) { //此为是否要启动便连接es,可自行增加配置文件设置
connect();
}
createBuiltInIndices(); //创建索引
}
我们来看看创建索引这个方法
private void createBuiltInIndices() {
String indexName;
BaseIndexModel model; //实体类基类
for (Class clazz : DataModelUtils.getBuiltInClazzes()) {
List<DataItem> dataItems = DataModelUtils.getModelDataItems(clazz);
try {
model = (BaseIndexModel) clazz.newInstance(); //通过反射实例化
indexName = model.getIndexName();
if (!indexExists(indexName)) { //判断索引是否存在,不存在则创建索引
createIndexNType(indexName, dataItems); //创建索引
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
}
}
大家看到这个地方可能有点迷糊,BaseIndexModel是啥,BaseIndexModel是我自定义的一个基类,所有要存入es的实体都继承这个基类,然后通过自行创建的配置文件properties:
people=cn.gzis.gxpt.core.biz.model.People
student=cn.gzis.gxpt.core.biz.enterprise.model.Student
DataModelUtils.getBuiltInClazzes()方法便是我自己编写的一个处理properties的静态方法,然后通过反射给每一个实体实例化,且基类中有一个getIndexName()方法,用来获取properties中的key,用key作为该实体在es中的索引名。
DataModelUtils.getModelDataItems(clazz)方法是通过反射获取该类所有字段,
最后把字段和索引名传入createIndexNType()方法中,用于创建索引。
接下来我们来看看创建type这个方法
public boolean createType(String indexName, Collection<DataItem> dataItems) {
if (StringUtils.isBlank(indexName) || null == dataItems || dataItems.isEmpty()) {
return false;
}
boolean flag;
logger.debug("准备创建Type...");
try {
XContentBuilder xcb = XContentFactory.jsonBuilder().startObject().startObject(ELASTICSEARCH_TYPE).startObject("properties"); //创建json结构
for (DataItem dataItem : dataItems) { //遍历数据项,需要有一个数据项的实体
xcb = xcb.startObject(dataItem.getEname())
.field("type", "text")
.field("store", "yes")
.field("fielddata", "true")
.startObject("fields")
.startObject("keyword")
.field("type", "keyword").field("ignore_above", 256)
.endObject();
if (DataItemType.NUMBER.equals(dataItem.getType())) { //根据类型创建mapping数据结构
xcb = xcb.startObject("number").field("type", "double").endObject();
}
// if (DataItemType.DATE.equals(dataItem.getType())) {
// xcb = xcb.startObject("date").field("type", "date").field("format", "yyyy-MM-dd").endObject();
// }
if (DataItemType.DATETIME.equals(dataItem.getType())) {
xcb = xcb.startObject("date").field("type", "date").field("format", "yyyy-MM-dd HH:mm:ss || yyyy-MM-dd HH:mm:ss.SSS || yyyy-MM-dd || yyyyMM").endObject();
}
xcb.endObject().endObject();
}
logger.debug("创建Type...");
flag = getAdminClient().indices().preparePutMapping(indexName).setType(ELASTICSEARCH_TYPE).setSource(xcb.endObject().endObject().endObject()).get().isAcknowledged(); //通过es api创建索引
logger.debug(flag ? "创建Type成功!" : "创建Type失败!");
return flag;
} catch (IOException e) {
logger.error(e.getMessage(), e);
return false;
}
}
在这个地方,我使用了es的xContent去创建一个Mappng映射的json,然后遍历每个实体的数据项(就是字段),根据字段类型创建索引类型。
到了最后一步利用es的java api,通过setSource把mapping结构传递进去,我们的索引就基本创建成功了!
最后说一句,elasticsearch广泛运用于大数据实时查询中,是学大数据必不可少的一门框架技术,特别是es的聚合统计有利于数据计算和分析,希望大家可以多多了解交流
更多推荐
所有评论(0)