Elasticsearch Java Client入门

Wesley13
• 阅读 691

序言

Elasticsearch(名称太长,后面简称ES)作为一个搜索引擎,目前可谓是如日中天,几乎和solr齐驾并驱。关于他能做什么,跟云计算有什么关系,在此不再描述。但是ES的官方文档,特别是关于java的客户端文档,真是少的可怜,甚至连个完整的增删改的示例都没有。在此,我就献丑了。
在开始讲解之前,还是先做个铺垫,为了能够有一个可以索引的模型,我们自定义了一个模型,暂时起个名称叫LogModel吧,这个模型有各种数据类型,int,long,String,list,但千万不要认为这是跟记录日志有关的一个模型。作为索引的一个最简单模型。代码如下:

import java.util.ArrayList;  
import java.util.List;  
import java.util.Random;  
import java.util.UUID;  
/** * 瞎编的一个模型,跟日志基本没有关系 * @author donlian */  
public class LogModel {  
    //主ID 
    private long id;  
    //次ID 
    private int subId;  
    /** * 系统名称 */  
    private String systemName;  
    private String host;  

    //日志描述 
    private String desc;  
    private List<Integer> catIds;  
    public LogModel(){  
        Random random = new Random();  
        this.id = Math.abs(random.nextLong());  
        int subId = Math.abs(random.nextInt());  
        this.subId = subId;  
        List<Integer> list = new ArrayList<Integer>(5);  
        for(int i=0;i<5;i++){  
            list.add(Math.abs(random.nextInt()));  
        }  
        this.catIds = list;  
        this.systemName = subId%1 == 0?"oa":"cms";  
        this.host = subId%1 == 0?"10.0.0.1":"10.2.0.1";  
        this.desc = "中文" + UUID.randomUUID().toString();  
    }  
    public LogModel(long id,int subId,String sysName,String host,String desc,List<Integer> catIds){  
        this.id = id;  
        this.subId = subId;  
        this.systemName = sysName;  
        this.host = host;  
        this.desc = desc;  
        this.catIds = catIds;  
    }  
...//省去get,set方法 
} 

同时,因为ES在索引的时候,一般都用json格式,因此,使用jackson定义了一个将对象转化成json的工具类,也很简单,代码:

public class ESUtils {  
    private static ObjectMapper objectMapper = new ObjectMapper();  
    public static String toJson(Object o){  
        try {  
            return objectMapper.writeValueAsString(o);  
        } catch (JsonProcessingException e) {  
            e.printStackTrace();  
        }  
        return "";  
    }  
}

在开始进行操作ES服务器之前,我们必须得获得ES的API,简单介绍一下ES操作服务器的两种方式,一种是使用Node方式,即本机也启动一个ES,然后跟服务器的ES进行通信,这个node甚至还能存储(奇怪,一般需要这样的方式吗?),另一种,就是下面我介绍的这一种,通过一个对象使用http协议跟服务器进行交互。
获得一个ES客户端API的代码如下:

Settings settings = ImmutableSettings.settingsBuilder()  
                //指定集群名称 
                .put("cluster.name", "elasticsearch")  
                //探测集群中机器状态 
                .put("client.transport.sniff", true).build();  
        /* * 创建客户端,所有的操作都由客户端开始,这个就好像是JDBC的Connection对象 * 用完记得要关闭 * 注意client里面包含了连接池,对于client而言用完之后需要关闭,但是针对连接而言不需要关闭 */  
        Client client = new TransportClient(settings)  
        .addTransportAddress(new InetSocketTransportAddress("192.168.1.106", 9300));  

Client对象,可以理解为数据库的Connection对象。好了,准备工作完成,下面就开始增删改查。
Client更类似与连接池

Index(增加)

ES里面的增加对象不叫什么add,save等,叫index。但无论叫什么名称,反正就是向ES服务器里面加数据。上面说过一个对象转json的工具类,其实ES的API中,是自带构建json的工具类的。

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 com.donlianli.es.ESUtils; 
import com.donlianli.es.model.LogModel; 
/** * 向ES添加索引对象 * @author donlian */  
public class IndexTest {  
    public static void main(String[] argv){  
        Settings settings = ImmutableSettings.settingsBuilder()  
                //指定集群名称  
                .put("cluster.name", "elasticsearch")  
                //探测集群中机器状态  
                .put("client.transport.sniff", true).build(); 
        /* * 创建客户端,所有的操作都由客户端开始,这个就好像是JDBC的Connection对象 * 用完记得要关闭 */  
        Client client = new TransportClient(settings)  
        .addTransportAddress(new InetSocketTransportAddress("192.168.1.106", 9300)); 
        String json = ESUtils.toJson(new LogModel()); 
        //在这里创建我们要索引的对象  
        IndexResponse response = client.prepareIndex("twitter", "tweet")  
                //必须为对象单独指定ID  
                .setId("1")  
                .setSource(json)  
                .execute()  
                .actionGet(); 
        //多次index这个版本号会变  
        System.out.println("response.version():"+response.version()); 
        client.close(); 
    }  
}  

运行这个代码,就向ES插入了一条数据,你运行两遍,还是一条。ES根据你设置的ID来设置对象,如果没有则插入,有则更新。每更新一次,对应的version加1.
好了,在次,使用以下命令,应该能够查询到一条记录了。

curl -XGET 'http://localhost:9200/twitter/tweet/1'  

delete(删除)

有了增加的例子,删除的例子也就好写了。增加是prepareIndex,删除是prepareDelete,查询就是PrepareGet。
代码如下:

import org.elasticsearch.action.delete.DeleteResponse; 
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 com.donlianli.es.ESUtils; 

public class DeleteTest {  
    public static void main(String[] argv){  
        Settings settings = ImmutableSettings.settingsBuilder()  
                //指定集群名称  
                .put("cluster.name", "elasticsearch")  
                //探测集群中机器状态  
                .put("client.transport.sniff", true).build(); 
        /* * 创建客户端,所有的操作都由客户端开始,这个就好像是JDBC的Connection对象 * 用完记得要关闭 */  
        Client client = new TransportClient(settings)  
        .addTransportAddress(new InetSocketTransportAddress("192.168.1.106", 9300)); 
        //在这里创建我们要索引的对象  
        DeleteResponse response = client.prepareDelete("twitter", "tweet", "1")  
                .execute().actionGet(); 
        System.out.println(response.getId()); 
        System.out.println(ESUtils.toJson(response.getHeaders())); 
    }  
}  

GET(查询)

import org.elasticsearch.action.get.GetResponse; 
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; 

public class GetTest {  
    public static void main(String[] argv){  
        Settings settings = ImmutableSettings.settingsBuilder()  
                //指定集群名称  
                .put("cluster.name", "elasticsearch")  
                //探测集群中机器状态  
                .put("client.transport.sniff", true).build(); 
        /* * 创建客户端,所有的操作都由客户端开始,这个就好像是JDBC的Connection对象 * 用完记得要关闭 */  
        Client client = new TransportClient(settings)  
        .addTransportAddress(new InetSocketTransportAddress("192.168.1.106", 9300)); 
        //在这里创建我们要索引的对象  
        GetResponse response = client.prepareGet("twitter", "tweet", "1")  
                .execute().actionGet(); 
        System.out.println("response.getId():"+response.getId()); 
        System.out.println("response.getSourceAsString():"+response.getSourceAsString()); 
    }  
}  

好了,增删改查的代码写完。至于搜索,那是一个比较深入的话题,我也在慢慢探索。我时间我会继续写下去。

对于ES的Java Client我觉得更多的是类似于JDBC连接池的概念。你不能在程序里不停的new client,所有的连接都可以使用同一个client来操作,类似于我们在JDBC里每一次的查询都会使用同一个连接池。极端情况下不断的实例化client会导致服务器达到最大连接数,从而是应用报错。根据经验,默认情况下client保留的连接数是15。

如有不同见解,欢迎留言讨论!

原文出自http://donlianli.iteye.com/blog/1902238

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Wesley13 Wesley13
3年前
Java日期时间API系列31
  时间戳是指格林威治时间1970年01月01日00时00分00秒起至现在的总毫秒数,是所有时间的基础,其他时间可以通过时间戳转换得到。Java中本来已经有相关获取时间戳的方法,Java8后增加新的类Instant等专用于处理时间戳问题。 1获取时间戳的方法和性能对比1.1获取时间戳方法Java8以前
Stella981 Stella981
3年前
Python之time模块的时间戳、时间字符串格式化与转换
Python处理时间和时间戳的内置模块就有time,和datetime两个,本文先说time模块。关于时间戳的几个概念时间戳,根据1970年1月1日00:00:00开始按秒计算的偏移量。时间元组(struct_time),包含9个元素。 time.struct_time(tm_y
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
为什么mysql不推荐使用雪花ID作为主键
作者:毛辰飞背景在mysql中设计表的时候,mysql官方推荐不要使用uuid或者不连续不重复的雪花id(long形且唯一),而是推荐连续自增的主键id,官方的推荐是auto_increment,那么为什么不建议采用uuid,使用uuid究
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这