ElasticSearch 攻略(二) Client 及简单 CRUD

本文涉及的产品
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
简介: es 算是个数据库,但木有 ODBC/JDBC 这样的“连接桥梁”。或者说这是一种区别于“传统观念”,新的 NoSQL 所带来了新的视角和理念(相对地),自然这些非关系型数据库那么更倾向于采用新的交换数据或者增删改查的模式——其中 HTTP API 就悄悄地成为一种约定成俗的模式,渐渐流行开来。

es 算是个数据库,但木有 ODBC/JDBC 这样的“连接桥梁”。或者说这是一种区别于“传统观念”,新的 NoSQL 所带来了新的视角和理念(相对地),自然这些非关系型数据库那么更倾向于采用新的交换数据或者增删改查的模式——其中 HTTP API 就悄悄地成为一种约定成俗的模式,渐渐流行开来。es 亦是如此。于是,無論什么语言都可以通过此 HTTP API 实现通讯。本身官方也提供一批语言的封装以方便开发者调用 es 里面的数据(称作 Client),另外 Client 还提供集群管理任务的 API。

es HTTP API 是典型的 RESTful API,所以 url 表示对资源的操作,例如 POST 新增,PUT 更新,GET 获取,DELETE 删除,HEAD 判断是否存在,此乃 REST API 之共性内容。除此之外,es 的 url 遵循一套规则,如:

http://localhost:9200/<index>/<type>/[<id>] 

index可以理解为数据库,type 理解为数据表,例如 /blog/article/1,就表示一个 index 为 blog,type 为aritcle,id 为1的 document。其中 index、type 是必须提供的,id 是可选的,不提供的话 es 会自动生成。


由于 es 本身是用 Java 写成的,那么使用 Java API 调 es 更是 Native 的感覺,理論上速度会更快。另外不得不说是 JavaScript Client。既然人家是 JSON-Friendly 的,那么首先一个 Node.js 的 Client 亦不在话下,因为天然的姻亲缘故使得 JSON 格式交换起来十分顺畅(参见官方 Guide)。好~不扯到 nodejs了,我们详细来看看 Java 的。

TransportClient

如同访问数据库先要连接数据一样,这种连接过程在 es 中称作连接集群 cluster。完成这样工作的是“传输客户端 TransportClient”。

// on startup

Client client = TransportClient.builder().build()
        .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("host1"), 9300))
        .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("host2"), 9300));

// on shutdown

client.close();

请注意,这里虽然有多个 host,但这不是加入 es 集群,只是指定了多个传输地址(TransportAddress)来查询多个库,其目的在于当一个服务(对应一个 TransportAddress)不可用时,client 会自动发现当前其他可用的 nodes(the current connected nodes)。理论上,Client 可以添加 es 集群中部分或全部 nodes,然后轮询“拿到”一个 node,届时client 可以和 es 集群进行通信和操作

这里是我本机上的例子,指定了集群的名称并批量插入索引数据。

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Map;

import org.elasticsearch.action.bulk.BulkRequestBuilder;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.client.Client;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;

public class Test {
	public static void main(String[] args) {
		Settings settings = Settings.settingsBuilder().put("cluster.name", "elasticsearch").build();

		try {

			Client client = TransportClient.builder().settings(settings).build()
					.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("localhost"), 9300));

			// 批量创建索引
			BulkRequestBuilder bulkRequest = client.prepareBulk();
			Map<String, Object> map = new HashMap<>();
			map.put("name", "Jack");

			IndexRequest request = client.prepareIndex("dept", "employee", "3433").setSource(map).request();
			bulkRequest.add(request);
			BulkResponse bulkResponse = bulkRequest.execute().actionGet();
			if (bulkResponse.hasFailures()) {
				System.out.println("批量创建索引错误!");
			}
			client.close();
			System.out.println("批量创建索引成功");
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
调用笔记两点:

  • 开始的时候使用了 InetAddress.getLocalHost() 虽然能返回本机 ip 但是不能发起连接的。后来改成 InetAddress.getByName("localhost") 才可以。
  • 访问端口是 9300 而非 HTTP 的 9200。估计不是走 HTTP 接口而是类似于 RMI 的远程请求。

CRUD

增删改查的 API 有,

  • Index 增加
  • Get 获取
  • Delete 删除
  • Update 更新

所有的 CRUD API 均是单索引的 API,index 参数只可送入一个 index 名称,或者 alias (别名)指向一个单索引。

另外下面是多文档的 API,

  • Multi Get 列表获取
  • Bulk 批量插入、删除

es 接受的格式

所謂文档 document,其结构本质就是一个 JSON。我们把文档进行索引工作就能快速被找到。安装传统的关系型数据库概念,相当于 Create 创建的工作。es 接受的就是这种 JSON 格式的文档。尽管是这种结构,可是还有几种数据的形态,下面我们逐一看看。

JSON 字符串

不消多说,最直接的是手写,

String json = "{" +
        "\"user\":\"kimchy\"," +
        "\"postDate\":\"2013-01-30\"," +
        "\"message\":\"trying out Elasticsearch\"" +
    "}";

或者 String 转换 byte[] 字节数组也可以,因为最终也是读取其 byte[] 形态,所以其他对象的 byte[] 类型也可以让 es Java API 读取。

Map

不用多说,应该要支持的。

Map<String, Object> json = new HashMap<>();// Java 7 有木有!
json.put("user","kimchy");
json.put("postDate",new Date());
json.put("message","trying out Elasticsearch");
Jackson

一說到 Json,大家可能会联想到 Java 的转换工具,如 Jackson——同样也是没问题的。

import com.fasterxml.jackson.databind.*;

// instance a json mapper
ObjectMapper mapper = new ObjectMapper(); // create once, reuse

// generate json
byte[] json = mapper.writeValueAsBytes(yourbeaninstance);
es 工具类

内置的工具类,还可以嵌套别的 builder。

import static org.elasticsearch.common.xcontent.XContentFactory.*;

XContentBuilder builder = jsonBuilder()
    .startObject() // 数组的话是 startArray(String
        .field("user", "kimchy")
        .field("postDate", new Date())
        .field("message", "trying out Elasticsearch")
    .endObject() // 数组的话是 endArray()

String json = builder.string();// 甚至可以通过 builder 来代替 Jackson 转换

保存起来

前面说了,所謂创建工作就是 index(此处的 index 作动词用)。

import static org.elasticsearch.common.xcontent.XContentFactory.*;
String json = "{" +
        "\"user\":\"kimchy\"," +
        "\"postDate\":\"2013-01-30\"," +
        "\"message\":\"trying out Elasticsearch\"" +
    "}";

IndexResponse response = client.prepareIndex("twitter", "tweet")
        .setSource(json)
        .get();

不过 prepareIndex 没有指定一个 id,现在指定以及换成 buidler 输入,

IndexResponse response = client.prepareIndex("twitter", "tweet", "1")
        .setSource(jsonBuilder()
                    .startObject()
                        .field("user", "kimchy")
                        .field("postDate", new Date())
                        .field("message", "trying out Elasticsearch")
                    .endObject()
                  )
        .get();

client.prepareIndex 参数可以是零个(其后必须使用 index(String) 和 type(String) 方法)、两个(client.prepareIndex(index,type))和三个(client.prepareIndex(index,type,id)),其中 index 类似于库名,type 类似于表名(和前面说过的一样),而 id 则是每条记录的惟一编码。通常情况下我们会把实体的唯一编码作为 es 的 id。如果不给 id 的时候,由 es 自动生成。

IndexResponse 是 es 创建完成索引后,回馈给你的实体。本例响应结果如下,

// Index name
String _index = response.getIndex();
// Type name
String _type = response.getType();
// Document ID (generated or not)
String _id = response.getId();
// Version (if it's the first time you index this document, you will get: 1)
long _version = response.getVersion();
// isCreated() is true if the document is a new one, false if it has been updated
boolean created = response.isCreated();

你可以从这个实体中获得相关有用的信息。

HTTP index API

另一边厢,可以瞧瞧 HTTP 接口同样效果,是不是更简单?

$ curl -XPUT 'http://localhost:9200/twitter/tweet/1' -d '{
    "user" : "kimchy",
    "post_date" : "2009-11-15T14:12:12",
    "message" : "trying out Elasticsearch"
}'

JSON 结果如下,

{
    "_shards" : {
        "total" : 10,
        "failed" : 0,
        "successful" : 10
    },
    "_index" : "twitter",
    "_type" : "tweet",
    "_id" : "1",
    "_version" : 1,
    "created" : true
}

index 批量添加建议使用bulk,效率高(减少通讯次数)。

获取、删除数据

插入记录之后,就可以获取了,

GetResponse response = client.prepareGet("twitter", "tweet", "1").get();

另可参考 HTTP API 的。

getResponse.getSourceAsString() 可以返回 JSON 字符串那么反序列化就非常简单了。

Person newPerson = mapper.readValue(getResponse.getSourceAsString(), Person.class);  
删除,

DeleteResponse response = client.prepareDelete("twitter", "tweet", "1").get();

另可参考 HTTP API 的。

相关实践学习
使用阿里云Elasticsearch体验信息检索加速
通过创建登录阿里云Elasticsearch集群,使用DataWorks将MySQL数据同步至Elasticsearch,体验多条件检索效果,简单展示数据同步和信息检索加速的过程和操作。
ElasticSearch 入门精讲
ElasticSearch是一个开源的、基于Lucene的、分布式、高扩展、高实时的搜索与数据分析引擎。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr(也是基于Lucene)。 ElasticSearch的实现原理主要分为以下几个步骤: 用户将数据提交到Elastic Search 数据库中 通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据 当用户搜索数据时候,再根据权重将结果排名、打分 将返回结果呈现给用户 Elasticsearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。
目录
相关文章
|
API 索引
【Elasticsearch】学好Elasticsearch系列-索引的CRUD
【Elasticsearch】学好Elasticsearch系列-索引的CRUD
96 0
|
6月前
|
NoSQL Java API
SpringBoot【ElasticSearch集成 02】Java HTTP Rest client for ElasticSearch Jest 客户端集成(依赖+配置+增删改查测试源码)推荐使用
SpringBoot【ElasticSearch集成 02】Java HTTP Rest client for ElasticSearch Jest 客户端集成(依赖+配置+增删改查测试源码)推荐使用
111 0
|
存储 JSON 自然语言处理
|
Java API 数据安全/隐私保护
Elasticsearch Java API Client 开发
本场景主要介绍如何使用 Elasticsearch Java API Client 进行开发,实现常用的 CRUD 操作。
|
存储 JSON 自然语言处理
三.全文检索ElasticSearch经典入门-索引CRUD&分词器&文档映射&文档CRUD
三.全文检索ElasticSearch经典入门-索引CRUD&分词器&文档映射&文档CRUD
|
Java 关系型数据库 MySQL
Spring boot 2.3.12集成ElasticSearch7.6.2并进行CRUD
Spring boot 2.3.12集成ElasticSearch7.6.2并进行CRUD
146 0
|
消息中间件 JavaScript 小程序
SpringBoot+ElasticSearch 实现模糊查询,批量CRUD,排序,分页,高亮
SpringBoot+ElasticSearch 实现模糊查询,批量CRUD,排序,分页,高亮
|
Java API 网络架构
ElasticSearch Client详解
详细分析介绍了Elasticsearch两大客户端TransportClient与RestHighLevelClient ,并详细介绍了es集群探测机制(client.transport.sniff)。
7316 0
|
索引
【ELK】(二)Elasticsearch 的 CRUD
【ELK】(二)Elasticsearch 的 CRUD
111 0
【ELK】(二)Elasticsearch 的 CRUD
|
JSON 负载均衡 Java
ElasticSearch Client详解
ElasticSearch Client详解
ElasticSearch Client详解