ElasticSearch编程
创建测试项目,导包
创建一个maven项目,导入ElasticSearch相关包
<dependencies>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>5.6.8</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>transport</artifactId>
<version>5.6.8</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-to-slf4j</artifactId>
<version>2.9.1</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.24</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
创建索引
@Test
//创建索引
public void createIndex() throws Exception{
//1.设置加入的集群
Settings settings = Settings.builder().put("cluster.name","my-elasticsearch").build();
//2.创建client连接对象
TransportClient client = new PreBuiltTransportClient(settings)
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("192.168.111.129"),9300));
//3.创建名称为blog2的索引
client.admin().indices().prepareCreate("blog2").get();
//4.释放资源
client.close();
}
运行结果可以在elasticsearch-head-master中看到
创建映射mapping
因为无论创建索引还是mapping,以及之后的创建数据和查询操作都需要创建client连接对象,所以我们将其封装成一个单独的方法。此处注解Before的作用为在点击运行test之前都会限制行一遍getTransportClient()方法
TransportClient client ;
@Before
public void getTransportClient() throws UnknownHostException {
Settings settings = Settings.builder().put("cluster.name","my-elasticsearch").build();
client = new PreBuiltTransportClient(settings)
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("192.168.111.129"), 9300));
}
创建映射
@Test
//创建映射
public void createMappings() throws Exception {
//添加映射
/**
"mappings": {
"article": {
"properties": {
"id": {
"store": true,
"type": "integer"
},
"title": {
"analyzer": "ik_smart",
"store": true,
"type": "text"
},
"content": {
"analyzer": "ik_smart",
"store": true,
"type": "text"
}
}
}
}
*/
XContentBuilder builder = XContentFactory.jsonBuilder()
.startObject()
.startObject("article")
.startObject("properties")
.startObject("id")
.field("type","integer").field("store","yes")
.endObject()
.startObject("title")
.field("type","string").field("store","yes").field("analyzer","ik_smart")
.endObject()
.startObject("content")
.field("type","string").field("store","yes").field("analyzer","ik_smart")
.endObject()
.endObject()
.endObject()
.endObject();
//创建映射
PutMappingRequest mapping = Requests.putMappingRequest("blog2")
.type("article").source(builder);
client.admin().indices().putMapping(mapping).get();
//释放资源
client.close();
}
运行后可以在elasticsearch-head-master中看到
建立文档操作
建立文档1–通过XContentBuilder
此处要注意id格式默认为长整型
@Test
//建立文档--通过XContentBuilder
public void createDoc() throws Exception{
//创建client对象
//创建一个文档对象
XContentBuilder builder = XContentFactory.jsonBuilder()
.startObject()
.field("id", 2L)
.field("title","桂林大暴雨")
.field("content","桂林下雨了!桂林又下雨了!")
.endObject();
//把文档对象添加到索引库
client.prepareIndex()
//设置索引名称
.setIndex("blog2")
//设置type
.setType("article")
//设置文档的id,如果不设置的话自动生成一个id
.setId("2")
//设置文档信息
.setSource(builder)
//执行操作
.get();
//关闭客户端
client.close();
}
可以在elasticsearch-head-master中看到
建立文档2–通过Jackson转换实体
字面意思通过传入对象的方式创建文档
首先创建Article实体类
public class Article {
private long id;
private String title;
private String content;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
然后使⽤Jackson转换实体
@Test
//创建文档第二种方式--通过ackson转换实体
public void createDoc2() throws Exception{
//创建一个Article对象
Article article = new Article();
//设置对象的属性
article.setId(3);
article.setTitle("桂林大暴雪");
article.setContent("这是不可能的!这是不可能的!");
//把article对象转换成json格式的字符串
ObjectMapper objectMapper = new ObjectMapper();
String jsonDocument = objectMapper.writeValueAsString(article);
System.out.println(jsonDocument);
//使用client对象把文档写入索引库
client.prepareIndex("blog2","article","3")
.setSource(jsonDocument, XContentType.JSON)
.get();
//关闭客户端
}
同样可以在elasticsearch-head-master中看到,文档同样创建成功
查询文档操作
TermQuery
TermQuery:对搜索的关键词不分词
@Test
//termQuery查询
public void testQueryByTerm() throws Exception{
//创建一个QueryBuilder对象
//参数1:要搜索的字段
//参数2:要搜索的关键词
QueryBuilder queryBuilder = QueryBuilders.termQuery("title","桂林暴雪");
//执行查询
SearchResponse searchResponse = client.prepareSearch("blog2")
.setTypes("article")
.setQuery(queryBuilder)
.get();
//得到查询结果
SearchHits searchHits = searchResponse.getHits();
//取查询结果的总记录数
System.out.println("查询结果总记录数:"+searchHits.getTotalHits());
//查询结果列表
Iterator<SearchHit> iterator = searchHits.iterator();
while(iterator.hasNext()) {
SearchHit searchHit = iterator.next();
//打印⽂档对象,以json格式输出
System.out.println(searchHit.getSourceAsString());
//取⽂档的属性
System.out.println("-----------⽂档的属性-----------");
Map<String, Object> document = searchHit.getSource();
System.out.println(document.get("id"));
System.out.println(document.get("title"));
System.out.println(document.get("content"));
}
//关闭client
client.close();
}
QueryString
query_string:搜索之前对搜索的关键词分词,搜索结果取决于分词器
@Test
public void testQueryByQueryString() throws Exception {
//创建⼀个QueryBuilder对象
//参数1:要搜索的字段
//参数2:要搜索的关键词
QueryBuilder queryBuilder = QueryBuilders.queryStringQuery("桂林暴雪").defaultField("title");
//执⾏查询
SearchResponse searchResponse = client.prepareSearch("blog2")
.setTypes("article")
.setQuery(queryBuilder)
.get();
//取查询结果
SearchHits searchHits = searchResponse.getHits();
//取查询结果的总记录数
System.out.println("查询结果总记录数:" + searchHits.getTotalHits());
//查询结果列表
Iterator<SearchHit> iterator = searchHits.iterator();
while(iterator.hasNext()) {
SearchHit searchHit = iterator.next();
//打印⽂档对象,以json格式输出
System.out.println(searchHit.getSourceAsString());
//取⽂档的属性
System.out.println("-----------⽂档的属性-----------");
Map<String, Object> document = searchHit.getSource();
System.out.println(document.get("id"));
System.out.println(document.get("title"));
System.out.println(document.get("content"));
}
//关闭client
client.close();
}
MatchQuery
match查询时,对查询字符串会进行分词处理。
@Test
public void testQueryByMatchQuery() throws Exception {
//创建⼀个QueryBuilder对象
//参数1:要搜索的字段
//参数2:要搜索的关键词
QueryBuilder queryBuilder = QueryBuilders.matchQuery("title", "桂暴雪");
//执⾏查询
SearchResponse searchResponse = client.prepareSearch("blog2")
.setTypes("article")
.setQuery(queryBuilder)
.get();
//取查询结果
SearchHits searchHits = searchResponse.getHits();
//取查询结果的总记录数
System.out.println("查询结果总记录数:" + searchHits.getTotalHits());
//查询结果列表
Iterator<SearchHit> iterator = searchHits.iterator();
while(iterator.hasNext()) {
SearchHit searchHit = iterator.next();
//打印⽂档对象,以json格式输出
System.out.println(searchHit.getSourceAsString());
//取⽂档的属性
System.out.println("-----------⽂档的属性-----------");
Map<String, Object> document = searchHit.getSource();
System.out.println(document.get("id"));
System.out.println(document.get("title"));
System.out.println(document.get("content"));
}
//关闭client
client.close();
}
查询后分页
//查询后分页方法
private void search(QueryBuilder queryBuilder) throws Exception {
//执⾏查询
SearchResponse searchResponse = client.prepareSearch("blog2")
.setTypes("article")
.setQuery(queryBuilder)
//设置分⻚信息
.setFrom(0)
//每⻚显示的⾏数
.setSize(5)
.get();
//取查询结果
SearchHits searchHits = searchResponse.getHits();
//取查询结果的总记录数
System.out.println("查询结果总记录数:" + searchHits.getTotalHits());
//查询结果列表
Iterator<SearchHit> iterator = searchHits.iterator();
while(iterator.hasNext()) {
SearchHit searchHit = iterator.next();
//打印⽂档对象,以json格式输出
System.out.println(searchHit.getSourceAsString());
//取⽂档的属性
System.out.println("-----------⽂档的属性");
Map<String, Object> document = searchHit.getSource();
System.out.println(document.get("id"));
System.out.println(document.get("title"));
System.out.println(document.get("content"));
}
//关闭client
client.close();
}
使用文档id查询
//使用文档ID查询文档
@Test
public void testSearchById() throws Exception {
//创建⼀个client对象
//创建⼀个查询对象
QueryBuilder queryBuilder = QueryBuilders.idsQuery().addIds("2", "3");
search(queryBuilder);
}
查询结果高亮操作
比如在京东商城搜索“笔记本”
通过开发者⼯具查看⾼亮数据的html代码实现:
ElasticSearch可以对查询出的内容中关键字部分进⾏标签和样式的设置,但是你需要告诉ElasticSearch
使⽤什么标签对⾼亮关键字进⾏包裹
代码实现如下:
//高亮代码实现
@Test
public void highlightSearchTest() throws Exception {
QueryBuilder queryBuilder = QueryBuilders.multiMatchQuery("桂林", "title", "content");
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.field("title").field("content");
highlightBuilder.preTags("<em>");
highlightBuilder.postTags("</em>");
//执⾏查询
SearchResponse searchResponse = client.prepareSearch("blog2")
.setTypes("article")
.setQuery(queryBuilder)
//设置⾼亮信息
.highlighter(highlightBuilder)
.get();
//取查询结果
SearchHits searchHits = searchResponse.getHits();
//取查询结果的总记录数
System.out.println("查询结果总记录数:" + searchHits.getTotalHits());
//查询结果列表
Iterator<SearchHit> iterator = searchHits.iterator();
while(iterator.hasNext()) {
SearchHit searchHit = iterator.next();
//取⽂档的属性
System.out.println("-----------⽂档的属性-----------");
Map<String, Object> document = searchHit.getSource();
System.out.println(document.get("id"));
System.out.println(document.get("title"));
System.out.println(document.get("content"));
System.out.println("************高亮结果************");
Map<String, HighlightField> highlightFields =
searchHit.getHighlightFields();
//取title⾼亮显示的结果
if (highlightFields.size() <=0) continue;
for (Map.Entry<String, HighlightField> entry :
highlightFields.entrySet()) {
System.out.println(entry.getKey() + ":\t" +
Arrays.toString(entry.getValue().getFragments()));
}
}
//关闭client
client.close();
}
查询结果如下