ElasticSearch集群API操作
前期准备
首先,pom需要导入的包如下:
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>6.0.0</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>transport</artifactId>
<version>6.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-to-slf4j</artifactId>
<version>2.12.1</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.30</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.5</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.10.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.10.1</version>
</dependency>
因为以下测试方法多,而每一次都需要进行client客户端的创建以及关闭,繁琐,因此为了简化代码。单独提出来
public static PreBuiltTransportClient client;
@Before
public void init() throws Exception {
// 创建一个配置文件
Settings settings = Settings.builder()
.put("cluster.name", "test")
.build();
client = new PreBuiltTransportClient(settings);
// 集群的ip以及端口
client.addTransportAddress(new TransportAddress(InetAddress.getByName("192.168.135.237"), 9301));
client.addTransportAddress(new TransportAddress(InetAddress.getByName("192.168.135.237"), 9302));
client.addTransportAddress(new TransportAddress(InetAddress.getByName("192.168.135.237"), 9303));
}
@After
public void close() {
client.close();
}
这样在执行某一个方法的时候,都会先执行Before的方法,再执行该方法,最后在执行After方法。
创建索引
@Test
public void testClusterCreateIndex() throws Exception {
// admin():获取Admin API,用indices()方法对索引进行操作
client.admin().indices().prepareCreate("cluster")
.get();
}
创建mapping
@Test
public void testCreateMapping() throws Exception {
XContentBuilder doc = XContentFactory.jsonBuilder()
.startObject()
.startObject("test-type")
.startObject("properties")
.startObject("id")
.field("type", "long")
.field("store", true)
.endObject()
.startObject("title")
.field("type", "text")
.field("store", true)
.endObject()
.startObject("content")
.field("type", "text")
.field("store", true)
.endObject()
.endObject()
.endObject()
.endObject();
// 把mapping信息设置到索引库当中
PutMappingResponse response = client.admin().indices()
// 设置要做映射的索引
.preparePutMapping("cluster")
// 设置要做映射的type
.setType("test-type")
// mapping 信息
.setSource(doc)
// 执行
.get();
System.out.println(response.isAcknowledged());
}
结果,可以使用postman进行查看并对照:
(其实不用写的这么繁琐,因为如store这一类的属性ES默认为true,不用我们特意写出来,只是为了让大家更好的看出这个mapping添加的一个结构才这么写的)
插入数据
利用XContentFactory插入
@Test
public void testInsertDocument() throws Exception {
XContentBuilder doc = XContentFactory.jsonBuilder()
// 代表一个开始
.startObject()
.field("id", "2")
.field("title", "wow,so good")
.field("content", "233333333333333355555555555555")
// 代表结束
.endObject();
client.prepareIndex()
// 设置索引名称
.setIndex("cluster")
// 设置ype
.setType("test-type")
.setId("1")
// 获取数据文档
.setSource(doc)
//执行
.get();
}
创建原生对象,转JSON插入
比如需要把Article这个对象的各个属性插入到ES当中,首先要创建一个对象
第一步:创建Article类:
public class Article {
private int id;
private String title;
private long content;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public long getContent() {
return content;
}
public void setContent(long content) {
this.content = content;
}
}
第二步:
@Test
public void testInsertDocument2() throws Exception {
Article article = new Article();
article.setId(101);
article.setTitle("hello");
article.setContent(666666666);
ObjectMapper objectMapper = new ObjectMapper();
String doc = objectMapper.writeValueAsString(article);
client.prepareIndex()
// 设置索引名称
.setIndex("cluster")
// 设置ype
.setType("test-type")
.setId("1")
.setSource(doc, XContentType.JSON)
.get();
}
查询
准备工作
写一个查询的方法:QueryBuilder为传入的参数
public void search(QueryBuilder queryBuilder) {
// 执行查询
SearchResponse response = client.prepareSearch("cluster")
.setTypes("test-type")
.setQuery(queryBuilder)
.get();
// 获取查询结果
SearchHits hits = response.getHits();
System.out.println("查询记录条数:" + hits.getTotalHits());
for (SearchHit hit : hits) {
// 打印文档对象
System.out.println(hit.getSourceAsString());
}
}
根据Id查询
@Test
public void testSearchById() throws Exception {
// 创建一个查询对象,使用idsQuery(),addids中的参数可以动态选多个
IdsQueryBuilder queryBuilder = QueryBuilders.idsQuery().addIds("1", "2", "3");
search(queryBuilder);
}
根据Term查询
@Test
public void testSearchByTerm() throws Exception {
// 创建一个查询对象,使用termQuery
// 参数1:要搜索的字段
// 参数2:要搜索的关键词
QueryBuilder queryBuilder = QueryBuilders.termQuery("title", "got");
search(queryBuilder);
}
根据字符串匹配查询
@Test
public void testStringQuery() throws Exception {
// 创建一个查询对象
// queryStringQuery:要匹配的字符串
// defaultField:在哪一个字段下去匹配对应的字符串
QueryBuilder queryBuilder = QueryBuilders.queryStringQuery("text")
.defaultField("title");
search(queryBuilder);
}
查询结果高亮度显示
public void search(QueryBuilder queryBuilder, String highLightField) {
// 创建Highlight对象
HighlightBuilder highlightBuilder = new HighlightBuilder();
// 设置需要高亮度显示的字段
highlightBuilder.field(highLightField);
// 设置样式的头
highlightBuilder.preTags("<span style=\"color:red\">");
// 设置样式的尾
highlightBuilder.postTags("</span>");
// 执行查询
SearchResponse response = client.prepareSearch("cluster")
.setTypes("test-type")
.setQuery(queryBuilder)
// 设置分页信息
.setFrom(0)
.setSize(3)
.highlighter(highlightBuilder)
.get();
// 获取查询结果
SearchHits hits = response.getHits();
System.out.println("查询记录条数:" + hits.getTotalHits());
for (SearchHit hit : hits) {
// 打印文档对象
System.out.println(hit.getSourceAsString());
System.out.println("****************高亮结果******************");
System.out.println(hit.getHighlightFields());
}
}
@Test
public void testQueryhighLight() throws Exception {
QueryBuilder queryBuilder = QueryBuilders.queryStringQuery("text")
.defaultField("title");
search(queryBuilder, "title");
}
结果:理论上是可以的,只是idea显示的问题,如果放在页面里,效果应该是输出的字段是红色的。
分页查询
分页查询只需要添加2个参数即可,在client.get()之前添加。
例如:
SearchResponse response = client.prepareSearch("cluster")
.setTypes("test-type")
.setQuery(queryBuilder)
// 设置分页信息
.setFrom(0)
.setSize(3)
.get();