在今天的文章中,我们来介绍如何使用Java来访问Elasticsearch。

首先,我们必须在我们的系统中安装Elasticsearch。

Maven 配置

针对Java的开发,我们必须在pom.xml中配置相应的Elasticsearch的信息。Mavev dependency定义如下:

        <dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>7.3.1</version>
</dependency>

这也是目前截止最新的Elasticsearch的版本。您可以随时使用之前提供的链接查看Maven Central托管的最新版本。

完成数据库的查询

建立一个简单的model

    package com.javacodegeeks.example;

    public class Person {

        private String personId;
private String name;
private String number; public String getNumber() {
return number;
} public void setNumber(String number) {
this.number = number;
} public String getPersonId() {
return personId;
} public void setPersonId(String personId) {
this.personId = personId;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} @Override
public String toString() {
return String.format("Person{personId='%s', name='%s', number='%s}", personId, name, number);
}
}

在这里,我们定义了一个简单的Person Model。

定义连接参数

我们将使用默认连接参数与Elasticsearch建立连接。 默认情况下,ES使用两个端口:9200和9201

        private static final String HOST = "localhost";
private static final int PORT_ONE = 9200;
private static final int PORT_TWO = 9201;
private static final String SCHEME = "http"; private static RestHighLevelClient restHighLevelClient;
private static ObjectMapper objectMapper = new ObjectMapper(); private static final String INDEX = "persondata";
private static final String TYPE = "_doc";

这里我们定义了一个叫做persondata的index,它的type是_doc。在最新的版本中,每个index只支持一个type。

如上面参数中所述,Elasticsearch使用两个端口9200和9201.第一个端口9200由Elasticsearch查询服务器使用,我们可以使用它通过RESTful API直接查询数据库。 第二个端口9201由REST服务器使用,外部客户端可以使用该端口连接并执行操作。

建立一个连接

我们将创建一个与Elasticsearch数据库建立连接的方法。 在建立与数据库的连接时,我们必须提供两个端口,因为只有这样,我们的应用程序才能连接到Elasticsearch服务器,我们将能够执行数据库操作。 以下是建立连接的代码。

        private static synchronized RestHighLevelClient makeConnection() {

            if(restHighLevelClient == null) {
restHighLevelClient = new RestHighLevelClient(
RestClient.builder(
new HttpHost(HOST, PORT_ONE, SCHEME),
new HttpHost(HOST, PORT_TWO, SCHEME)));
} return restHighLevelClient;
}

在这里,我们建立一个RestHighLevelClient的实例。具体的参数,可以参官方文档 Java High Level REST Client (https://www.elastic.co/guide/en/elasticsearch/client/java-rest/7.3/java-rest-high.html)。

请注意,我们在此处实现了Singleton Design模式,因此不会为ES创建多个连接,从而节省大量内存。

由于存在RestHighLevelClient,与Elasticsearch的连接是线程安全的。 初始化此连接的最佳时间是应用程序请求或向客户端发出第一个请求时。 初始化此连接客户端后,可以使用它来执行任何支持的API。

关掉一个连接

就像在早期版本的Elasticsearch中一样,我们使用TransportClient,一旦完成查询就关闭它,一旦数据库交互完成RestHighLevelClient,也需要关闭连接。 以下是如何做到这一点:

        private static synchronized void closeConnection() throws IOException {
restHighLevelClient.close();
restHighLevelClient = null;
}

我们还为RestHighLevelClient对象分配了null,以便Singleton模式可以保持一致。

插入一个文档

我们可以通过将键和值转换为HashMap将数据插入数据库。 ES数据库仅接受HashMap形式的值。 让我们看看如何实现这一目标的代码片段:

       private static Person insertPerson(Person person) {

            person.setPersonId(UUID.randomUUID().toString());
Map<String, Object> dataMap = new HashMap<String, Object>();
dataMap.put("name", person.getName());
dataMap.put("number", person.getNumber());
IndexRequest indexRequest = new IndexRequest(INDEX)
.id(person.getPersonId()).source(dataMap);
try {
IndexResponse response = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
} catch(ElasticsearchException e) {
e.getDetailedMessage();
} catch (java.io.IOException ex){
ex.getLocalizedMessage();
} /*
// The following is another way to do it
// More information https://www.elastic.co/guide/en/elasticsearch/client/java-rest/7.3/java-rest-high-document-index.html
String id = UUID.randomUUID().toString();
person.setPersonId(id);
IndexRequest request = new IndexRequest(INDEX);
request.id(id);
String jsonString = "{" +
"\"name\":" + "\"" + person.getName() + "\"" +
"}";
System.out.println("jsonString: " + jsonString);
request.source(jsonString, XContentType.JSON);
try {
IndexResponse response = restHighLevelClient.index(request, RequestOptions.DEFAULT);
} catch(ElasticsearchException e) {
e.getDetailedMessage();
} catch (java.io.IOException ex){
ex.getLocalizedMessage();
}
*/ return person;
}

就像上面代码中注释的那样。注释的代码的那一部分是另外一种方法。大家可以参照链接(https://www.elastic.co/guide/en/elasticsearch/client/java-rest/7.3/java-rest-high-document-index.html)获得更多的信息。

上面,我们使用Java的UUID类来创建对象的唯一标识符。 这样,我们就可以控制对象标识符的制作方式。我们其实也可以固定一个id去写。如果是这样的话,运行多次,只会更新之前的数据,并且version会自动每次运行后增加1。

请求上面存入的文档

完成将数据插入数据库后,我们可以通过向Elasticsearch数据库服务器发出GET请求来确认操作。 让我们看看如何完成此操作的代码片段:

 

       private static Person getPersonById(String id){

            GetRequest getPersonRequest = new GetRequest(INDEX, id);
GetResponse getResponse = null;
try {
getResponse = restHighLevelClient.get(getPersonRequest, RequestOptions.DEFAULT);
} catch (java.io.IOException e){
e.getLocalizedMessage();
}
return getResponse != null ?
objectMapper.convertValue(getResponse.getSourceAsMap(), Person.class) : null;
}

在这里,我们根据上面返回来得id来进行query,并返回数据。

在这个查询中,我们只提供了可以识别它的对象的主要信息,即索引,和它的唯一标识符id。 此外,我们得到的实际上是一个值的映射。

更新文档

我们可以通过首先使用其索引,类型和唯一标识符来标识资源,从而轻松地向Elasticsearch发出更新请求。 然后我们可以使用新的HashMap对象来更新Object中的任意数量的值。 这是一个示例代码段:


private static Person updatePersonById(String id, Person person){
UpdateRequest updateRequest = new UpdateRequest(INDEX, id)
.fetchSource(true); // Fetch Object after its update
try {
String personJson = objectMapper.writeValueAsString(person);
updateRequest.doc(personJson, XContentType.JSON);
UpdateResponse updateResponse = restHighLevelClient.update(updateRequest, RequestOptions.DEFAULT);
return objectMapper.convertValue(updateResponse.getGetResult().sourceAsMap(), Person.class);
}catch (JsonProcessingException e){
e.getMessage();
} catch (java.io.IOException e){
e.getLocalizedMessage();
}
System.out.println("Unable to update person");
return null;
}

删除文档

最后,我们可以通过简单地使用其索引,类型和唯一标识符来标识资源来删除数据。 让我们看一下如何完成此操作的代码片段

        private static void deletePersonById(String id) {
DeleteRequest deleteRequest = new DeleteRequest(INDEX, TYPE, id);
try {
DeleteResponse deleteResponse = restHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);
} catch (java.io.IOException e) {
e.getLocalizedMessage();
}
}

我们根据传入的id来删除相应的文档。当然我们也可以做查询删除。

运行我们的应用

让我们通过执行上面提到的所有操作来尝试我们的应用程序。 由于这是一个普通的Java应用程序,我们将调用这些方法中的每一个并打印操作结果:

       public static void main(String[] args) throws IOException {

            makeConnection();

            Person person = new Person();
person.setName("张三");
System.out.println("Inserting a new Person with name " + person.getName());
person.setNumber("111111");
person = insertPerson(person);
System.out.println("Person inserted --> " + person); person = new Person();
person.setName("姚明");
System.out.println("Inserting a new Person with name " + person.getName());
person.setNumber("222222");
person = insertPerson(person);
System.out.println("Person inserted --> " + person); person.setName("李四");
System.out.println("Changing name to " + person.getName());
updatePersonById(person.getPersonId(), person);
System.out.println("Person updated --> " + person); System.out.println("Searching for all documents");
SearchResponse response = searchAll();
System.out.println(response); System.out.println("Searching for a term");
response = searchTerm();
System.out.println(response); System.out.println("Match a query");
response = matchQuery();
System.out.println(response); System.out.println("Getting 李四");
Person personFromDB = getPersonById(person.getPersonId());
System.out.println("Person from DB --> " + personFromDB); System.out.println("Deleting " + person.getName());
deletePersonById(personFromDB.getPersonId());
System.out.println("Person " + person.getName() + " deleted!"); closeConnection();
}

运行的结果如下:

    Inserting a new Person with name 张三
Person inserted --> Person{personId='33f4162e-0a68-4e66-8717-851516272185', name='张三', number='111111}
Inserting a new Person with name 姚明
Person inserted --> Person{personId='9b477529-6e79-42e8-a50a-21b2d8bc4c13', name='姚明', number='222222}
Changing name to 李四
Person updated --> Person{personId='9b477529-6e79-42e8-a50a-21b2d8bc4c13', name='李四', number='222222}
Searching for all documents
{"took":0,"timed_out":false,"_shards":{"total":1,"successful":1,"skipped":0,"failed":0},"hits":{"total":{"value":4,"relation":"eq"},"max_score":1.0,"hits":[{"_index":"persondata","_type":"_doc","_id":"52425a44-dc06-49ca-b3df-26a8b341391c","_score":1.0,"_source":{"number":"111111","name":"张三"}},{"_index":"persondata","_type":"_doc","_id":"c76b8670-ed00-4212-b47b-46bc85d588b6","_score":1.0,"_source":{"number":"111111","name":"张三"}},{"_index":"persondata","_type":"_doc","_id":"b8bf0466-0ea5-43e0-8188-c0712812fb9a","_score":1.0,"_source":{"number":"111111","name":"张三"}},{"_index":"persondata","_type":"_doc","_id":"468dabe4-8f50-4667-a165-9ce6e015cb76","_score":1.0,"_source":{"number":"222222","name":"李四","personId":"468dabe4-8f50-4667-a165-9ce6e015cb76"}}]}}
Searching for a term
{"took":0,"timed_out":false,"_shards":{"total":1,"successful":1,"skipped":0,"failed":0},"hits":{"total":{"value":3,"relation":"eq"},"max_score":0.9444616,"hits":[{"_index":"persondata","_type":"_doc","_id":"52425a44-dc06-49ca-b3df-26a8b341391c","_score":0.9444616,"_source":{"number":"111111","name":"张三"}},{"_index":"persondata","_type":"_doc","_id":"c76b8670-ed00-4212-b47b-46bc85d588b6","_score":0.9444616,"_source":{"number":"111111","name":"张三"}},{"_index":"persondata","_type":"_doc","_id":"b8bf0466-0ea5-43e0-8188-c0712812fb9a","_score":0.9444616,"_source":{"number":"111111","name":"张三"}}]}}
Match a query
{"took":0,"timed_out":false,"_shards":{"total":1,"successful":1,"skipped":0,"failed":0},"hits":{"total":{"value":3,"relation":"eq"},"max_score":1.8889232,"hits":[{"_index":"persondata","_type":"_doc","_id":"52425a44-dc06-49ca-b3df-26a8b341391c","_score":1.8889232,"_source":{"number":"111111","name":"张三"}},{"_index":"persondata","_type":"_doc","_id":"c76b8670-ed00-4212-b47b-46bc85d588b6","_score":1.8889232,"_source":{"number":"111111","name":"张三"}},{"_index":"persondata","_type":"_doc","_id":"b8bf0466-0ea5-43e0-8188-c0712812fb9a","_score":1.8889232,"_source":{"number":"111111","name":"张三"}}]}}
Getting 李四
Person from DB --> Person{personId='9b477529-6e79-42e8-a50a-21b2d8bc4c13', name='李四', number='222222}

整个项目的源码可以在地址找到:https://github.com/liu-xiao-guo/elastic-java

更多资料:

【1】使用RestHighLevelClient时单个索引速度很慢(https://discuss.elastic.co/t/resthighlevelclient/170293)

Elasticsearch:Java 运用示例的更多相关文章

  1. Elasticsearch Java client(ES Client 简介、Java REST Client、Java Client、Spring Data Elasticsearch)

    elasticsearch系列七:ES Java客户端-Elasticsearch Java client(ES Client 简介.Java REST Client.Java Client.Spri ...

  2. Elasticsearch 邻近查询示例

    Elasticsearch 邻近查询示例(全切分分词) JAVA API方式: SpanNearQueryBuilder span = QueryBuilders.spanNearQuery(); s ...

  3. Elasticsearch Java API深入详解

    0.题记 之前Elasticsearch的应用比较多,但大多集中在关系型.非关系型数据库与Elasticsearch之间的同步.以上内容完成了Elasticsearch所需要的基础数据量的供给.但想要 ...

  4. 正则表达式学习笔记(附:Java版示例代码)

    具体学习推荐:正则表达式30分钟入门教程 .         除换行符以外的任意字符\w      word,正常字符,可以当做变量名的,字母.数字.下划线.汉字\s        space,空白符 ...

  5. [搜索]ElasticSearch Java Api(一) -添加数据创建索引

    转载:http://blog.csdn.net/napoay/article/details/51707023 ElasticSearch JAVA API官网文档:https://www.elast ...

  6. Elasticsearch java api 基本搜索部分详解

    文档是结合几个博客整理出来的,内容大部分为转载内容.在使用过程中,对一些疑问点进行了整理与解析. Elasticsearch java api 基本搜索部分详解 ElasticSearch 常用的查询 ...

  7. Elasticsearch java api 常用查询方法QueryBuilder构造举例

    转载:http://m.blog.csdn.net/u012546526/article/details/74184769 Elasticsearch java api 常用查询方法QueryBuil ...

  8. Elasticsearch Java Rest Client API 整理总结 (二) —— SearchAPI

    目录 引言 Search APIs Search API Search Request 可选参数 使用 SearchSourceBuilder 构建查询条件 指定排序 高亮请求 聚合请求 建议请求 R ...

  9. Elasticsearch Java Rest Client API 整理总结 (三)——Building Queries

    目录 上篇回顾 Building Queries 匹配所有的查询 全文查询 Full Text Queries 什么是全文查询? Match 全文查询 API 列表 基于词项的查询 Term Term ...

  10. State of the official Elasticsearch Java clients

    Elasticsearch Java Clients | Elastic https://www.elastic.co/blog/state-of-the-official-elasticsearch ...

随机推荐

  1. 写出个灵活的系统竟然可以如此简单!小白也能写出高级的Java业务!

    一 最近正好公司里有个需求,一个短信业务接了多个第三方供应商,某些业务需要查询第三方供应商剩余的短信包数量去选择剩余量最多的渠道去批量发送.有些业务是指定了某个短信供应商,有些场景需要根据业务的值去动 ...

  2. pop!_OS换国内源

    今天给电脑换源了,虽然本来的源大部分好像也都连的上(不知道是不是错觉)换的这个:阿里云镜像开源站 先进入存放源的目录:` cd /etc/apt 里面有这些文件: sources.list是要修改的, ...

  3. 【python】下载中国大学MOOC的视频

    [python]下载中国大学MOOC的视频 脚本目标: 输入课程id和cookie下载整个课程的视频文件,方便复习时候看 网站的反爬机制分析: 分析数据包的目的:找到获取m3u8文件的路径 1. 从第 ...

  4. Solution -「线段树」题目集合

    T1 无聊的数列 来自:Link flag 帖先从水题入手. 首先分析题目,它是以等差数列为原型进行的修改.等差数列一大性质就是其差分数列的值除第一项以外均相等. 于是不难想到使用差分数列进行维护. ...

  5. 为什么Java有GC调优而没听说过有CLR的GC调优?

    前言 在很多的场合我都遇到过一些群友提这样的一些问题: 为什么Java有GC调优而CLR没有听说过有GC调优呢? 到底是Java的JVM GC比较强还是C#使用的.NET CLR的GC比较强呢? 其实 ...

  6. Dubbo源码(五) - 服务目录

    前言 本文基于Dubbo2.6.x版本,中文注释版源码已上传github:xiaoguyu/dubbo 今天,来聊聊Dubbo的服务目录(Directory).下面是官方文档对服务目录的定义: 服务目 ...

  7. MODBUS转PROFINET网关将电力智能监控仪表接入PROFINET网络案例

    本案例控制的主要对象是变送器的显示与报警.系统主PLC 选用西门子CPU,通过小疆智控MODBUS 转 PROFINET网关GW-PN5001采集IM300电力智能监控仪数据. 1.首先加入 GSD ...

  8. HttpServletRequest 类

    目录 HttpServletRequest类有什么作用 HttpServletRequest 类的常用方法 如何获取请求参数 doGet 请求的中文乱码解决: POST 请求的中文乱码解决 请求的转发 ...

  9. DolphinScheduler 线上 Meetup 视频回放(07.25)

    上周六下午 DolphinScheduler 社区联合 Doris 社区进行了 2020 年首次线上 Meetup,各位讲师都做了非常精彩的分享,也吸引了 1900 多位技术伙伴观看. 其中 Dolp ...

  10. Luogu3267 [JLOI2016/SHOI2016]侦察守卫 (树形DP)

    树形DP,一脸蒙蔽.看了题解才发现它转移状态与方程真不愧神题! \(f[x][y]\)表示\(x\)的\(y\)层以下的所有点都已经覆盖完,还需要覆盖上面的\(y\)层的最小代价. \(g[x][y] ...