package com.xiangshuai.es;
import com.alibaba.fastjson.JSONObject;
import com.xiangshuai.es.entity.Hello;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.transport.client.PreBuiltTransportClient;
import org.junit.jupiter.api.Test;
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
* @author lqx-代码和配套的其他资料都在E(我的网盘\我的笔记):\学习文档子目录压缩\框架\全文检索\Elasticsearch\非springdata-elasticsearch版本elasticsearch-6.2.1
* @ClassName ElasticsearchClient
* @description 前提先搭建es群,并将ik分词器放入es服务器中,启动es集群,启动head,参考
E:\学习文档子目录压缩\框架\全文检索\Elasticsearch\es代建1.txt
* @date 2020/5/17 11:29
*/
public class ElasticsearchClient {
/**
* @author lqx
* @ClassName ElasticsearchClient
* @description 百度org.elasticsearch.client.transport创建索引库--索引库相当于数据库
* 实现创建索引库步骤:
1.创建一个Settings对象,相当于是一个配置信息。主要配置集群的名称。
2.创建一个客户端Client对象。
3.使用client对象创建一个索引库。
4.关闭client对象。
* @date 2020/5/17 11:29
*/
@Test
public void createIndex(){
PreBuiltTransportClient client=null;
try {
//1.创建一个Setting对象,相当于配置文件主要放集群名
Settings settings = Settings.builder().put("cluster.name", "lqxtest").build();
//2.创建一个客户端client对象-相对于postman或head
client = new PreBuiltTransportClient(settings);
// 指定集群中节点的列表
client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9301));
client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9302));
client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9303));
// 3.使用client对象创建一个索引库,索引库名称为index_hello(前面为设置,get()为执行操作)
client.admin().indices().prepareCreate("index_hello").get();
//4.关闭client对象
}catch (Exception e){
e.printStackTrace();
}finally {
if(client!=null){
client.close();
}
}
}
/**
* 给索引库创建mappings
* @throws Exception
*/
@Test
public void setMapping() throws Exception {
//1、创建一个setting对象
Settings settings = Settings.builder().
put("cluster.name", "lqxtest").build();
//2、创建一个TransportClient对象,
TransportClient client = new PreBuiltTransportClient(settings)
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9301))
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9302))
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9303));
//3、创建一个Mappings信息
/* {
"article":{
"properties":{
"id":{
"type":"long",
"store":true
},
"title":{
"type":"text",
"store":true,
"analyzer":"ik_smart"
},
"content":{
"type":"text",
"store":true,
"analyzer":"ik_smart"
}
}
}
}*/
XContentBuilder builder= XContentFactory.jsonBuilder()
.startObject()
.startObject("hello") //如果索引相当于数据库,那么hello相当于表名
.startObject("properties")
.startObject("id")
.field("type","long")
.field("store",true)
.endObject()
.startObject("title")
.field("type","text")
.field("store",true)
.field("analyzer","ik_smart")
.endObject()
.startObject("content")
.field("type","text")
.field("store",true)
.field("analyzer","ik_smart")
.endObject()
.startObject("ss")
.field("type","text")
.field("store",true)
.field("analyzer","ik_max_word")
.field("search_analyzer","ik_smart")
.endObject()
.endObject()
.endObject()
.endObject();
//4、使用client向es服务器发送mapping信息
client.admin().indices()
//设置要做映射的索引--数据库
.preparePutMapping("index_hello")
//设置要做映射的type-表名
.setType("hello")
//mapping信息,可以使XContenxtBuilder对象,也可以使json格式的字符串
.setSource(builder)
//执行操作
.get();
//5、关闭client
client.close();
}
/**
* 创建文档--XContentBuilder
* @throws Exception
*/
@Test
public void addDoc() throws Exception {
//1、创建一个setting对象
Settings settings = Settings.builder().
put("cluster.name", "lqxtest").build();
//2、创建一个TransportClient对象,
TransportClient client = new PreBuiltTransportClient(settings)
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9301))
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9302))
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9303));
//3、创建一个文档对象
XContentBuilder builder= XContentFactory.jsonBuilder()
.startObject()
.field("id", 1L)
.field("title", "Bootstrap开发框")
.field("content", "\"Bootstrap是由Twitter推出的一个前台页面开发框架,在行业之中使用较为广泛。此开发框架包 含了大量的CSS、JS程序代码,可以帮助开发者(尤其是不擅长页面开发的程序人员)轻松的实现一个不受浏览器限制的 精美界面效果")
.field("ss", "ss测试Bootstrap开发框")
.endObject();
//4、使用client向es服务器发送文档信息
client.prepareIndex()
//设置要操作的索引库--数据库
.setIndex("index_hello")
//设置要做映射的type-表名
.setType("hello")
//设置id,不设置自动会生产一个id
.setId("1")
//设置文档信息
.setSource(builder)
//执行操作
.get();
client.close();
}
/**
* 创建文档--以json格式把文档对象插入索引库
* @throws Exception
*/
@Test
public void addDoc2() throws Exception {
//创建文档对象
Hello hi=new Hello();
hi.setId(2L);
hi.setContent("以json格式把文档对象插入索引库");
hi.setSs("以json格式ss");
hi.setTitle("son格式测试");
//将文档对象转换成json格式
String hiJson= JSONObject.toJSONString(hi);
System.out.println(hiJson);
//使用client对象将json对象文档写入索引库
TransportClient client = ElasticsearchClient.getClient();
client.prepareIndex("index_hello","hello","2")
.setSource(hiJson, XContentType.JSON).get();
//关闭客服端client
client.close();
}
/**
* 创建文档--以json格式把文档对象插入索引库
* 为了模拟分页查询用循环多插入几条数据
* @throws Exception
*/
@Test
public void addDoc3() throws Exception {
//使用client对象将json对象文档写入索引库
TransportClient client = ElasticsearchClient.getClient();
for(int i=5;i<100;i++){
//创建文档对象
Hello hi=new Hello();
hi.setId(Long.parseLong(i+""));
hi.setContent(i+"美方动用国家力量,以所谓国家安全为借口,滥用出口管制等措施,对他国特定企业持续打压、遏制,是对市场原则和公平竞争的破坏,是对国际经贸基本规则的无视,更是对全球产业链供应链安全的严重威胁。这损害中国企业利益,损害美国企业利益,也损害其他国家企业的利益");
hi.setSs("以json格式ss");
hi.setTitle("美方针对华为出台出口管制新规 商务部回应"+i);
//将文档对象转换成json格式
String hiJson= JSONObject.toJSONString(hi);
System.out.println(hiJson);
client.prepareIndex("index_hello","hello",i+"")
.setSource(hiJson, XContentType.JSON).get();
}
//关闭客服端client
client.close();
}
public static TransportClient getClient(){
TransportClient client = null;
try {
//1、创建一个setting对象
Settings settings = Settings.builder().
put("cluster.name", "lqxtest").build();
//2、创建一个TransportClient对象,
client = new PreBuiltTransportClient(settings)
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9301))
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9302))
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9303));
} catch (UnknownHostException e) {
e.printStackTrace();
}
return client;
}
}
#####################################################################
package com.xiangshuai.es;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.transport.client.PreBuiltTransportClient;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import javax.swing.text.Highlighter;
import javax.swing.text.StyledEditorKit;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Iterator;
import java.util.Map;
/**
* @author lqx
* @ClassName SearchIndex
* @description 代码和配套的其他资料都在E(我的网盘\我的笔记):\学习文档子目录压缩\框架\全文检索\Elasticsearch\非springdata-elasticsearch版本elasticsearch-6.2.1
* @date 2020/5/17 16:51
*/
public class SearchIndex {
private TransportClient client;
@Before
public void initClient(){
try {
//1、创建一个setting对象
Settings settings = Settings.builder().
put("cluster.name", "lqxtest").build();
//2、创建一个TransportClient对象,
client = new PreBuiltTransportClient(settings)
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9301))
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9302))
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9303));
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
/**
* 使用es客户端实现搜索
* 1.根据id搜索
* 2.根据Term查询 (关键字)
* 3.QueryString查询方式 (带分析的查询)
* 查询步骤套路
* 1) 创建一个Client对象
* 2) 创建一个查询对象,可以使用QueryBuilders工具类型创建QueryBuilder对象
* 3)使用client执行查询
* 4) 得到查询的结果
* 5) 取查询结果的总记录数
* 6) 取查询结果列表
* 7) 关闭client
*/
//1.根据id搜索
@Test
public void searchById(){
// 1) 创建一个Client对象--@before已经帮我们做了
// 2) 创建一个查询对象,可以使用QueryBuilders工具类型创建QueryBuilder对象
IdsQueryBuilder idsQueryBuilder = QueryBuilders.idsQuery().addIds("1", "2");//查id为1,2的记录
searchQueryBuilder(idsQueryBuilder);
}
//2.根据Term查询 (关键字)
@Test
public void searchByTerm(){
// 1) 创建一个Client对象--@before已经帮我们做了
// 2) 创建一个查询对象,可以使用QueryBuilders工具类型创建QueryBuilder对象
//参数1:要搜索的字段
//参数2:要搜索的关键字
TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("content", "框架");
searchQueryBuilder(termQueryBuilder);
}
/*
3.QueryString查询方式 (带分析的查询) --3.1指定默认Term就和Term查询一样,
--3.2不指定Term,就是在索引库,表的所有域-相当于所有字段中查询
不分页
*/
@Test
public void searchByQueryString(){
// 1) 创建一个Client对象--@before已经帮我们做了
// 2) 创建一个查询对象,可以使用QueryBuilders工具类型创建QueryBuilder对象
//参数1:要搜索的关键字
/* QueryStringQueryBuilder queryStringQueryBuilder = QueryBuilders.queryStringQuery("ss")
.defaultField("title");//参数2:指点默认域-相当于字段*/
QueryStringQueryBuilder queryStringQueryBuilder = QueryBuilders.queryStringQuery("ss");
searchQueryBuilder(queryStringQueryBuilder);
}
/*
3.QueryString查询方式 (带分析的查询) --3.1指定默认Term就和Term查询一样,
--3.2不指定Term,就是在索引库,表的所有域-相当于所有字段中查询
分页
*/
@Test
public void searchByQueryStringLimit(){
// 1) 创建一个Client对象--@before已经帮我们做了
// 2) 创建一个查询对象,可以使用QueryBuilders工具类型创建QueryBuilder对象
//参数1:要搜索的关键字
/* QueryStringQueryBuilder queryStringQueryBuilder = QueryBuilders.queryStringQuery("ss")
.defaultField("title");//参数2:指点默认域-相当于字段*/
QueryStringQueryBuilder queryStringQueryBuilder = QueryBuilders.queryStringQuery("以所谓国家安全为借口");
searchQueryBuilderByLimit(queryStringQueryBuilder,3,5);
}
/*
3.QueryString查询方式 (带分析的查询)并且高亮显示 --3.1指定默认Term就和Term查询一样,
--3.2不指定Term,就是在索引库,表的所有域-相当于所有字段中查询
分页
*/
@Test
public void searchByQueryStringLimitAndHighlight(){
// 1) 创建一个Client对象--@before已经帮我们做了
// 2) 创建一个查询对象,可以使用QueryBuilders工具类型创建QueryBuilder对象
//参数1:要搜索的关键字
/* QueryStringQueryBuilder queryStringQueryBuilder = QueryBuilders.queryStringQuery("ss")
.defaultField("title");//参数2:指点默认域-相当于字段*/
QueryStringQueryBuilder queryStringQueryBuilder = QueryBuilders.queryStringQuery("以所谓国家安全为借口");
searchQueryBuilderByLimitAndHighlight(queryStringQueryBuilder,3,5,"title");
}
/**
* @Description: 不分页查询
* @Author: lqx
* @Date: 2020/5/17 18:36
* @param queryBuilder: 搜获方式,1.根据id搜索 2.根据Term查询 (关键字) 3.QueryString查询方式 (带分析的查询)
* @return: void
**/
public void searchQueryBuilder(QueryBuilder queryBuilder){
// 3)使用client执行查询
SearchResponse searchResponse = client.prepareSearch("index_hello")//索引库--类型
.setTypes("hello")//即数据库--表
.setQuery(queryBuilder)
.get();
// 4) 得到查询的结果
SearchHits hits = searchResponse.getHits();
// 5) 取查询结果的总记录数
System.out.println("查询结果总记录数:" + hits.getTotalHits());
// 6) 取查询结果列表
Iterator<SearchHit> iterator = hits.iterator();
while (iterator.hasNext()){
SearchHit searchHit = iterator.next();
System.out.println(searchHit.getSourceAsString());//以json格式输出文档对象
Map<String, Object> source = searchHit.getSource();//文档对象
source.forEach((key,value)->{
System.out.println("key:"+key+"---value:"+value);
});
System.out.println("------------------>>>>>>>");
}
// 7) 关闭client
}
/***
* @Description: 分页查询-注意我这里没有考虑查不到结果的情况--为了程序健壮性需对分页查询结果的各种可能做处理
* @Author: lqx
* @Date: 2020/5/17 18:36
* @param queryBuilder: 搜获方式,1.根据id搜索 2.根据Term查询 (关键字) 3.QueryString查询方式 (带分析的查询)
* @param page: 查询页码
* @param limit: 每页显示条数
* @return: void
**/
public void searchQueryBuilderByLimit(QueryBuilder queryBuilder,int page,int limit){
// 3)使用client执行查询
SearchResponse searchResponse = client.prepareSearch("index_hello")//索引库--类型
.setTypes("hello")//即数据库--表
.setQuery(queryBuilder)
.setFrom((page-1)*limit)//从index第几条开始,和mysql limit一样是从0开始的
.setSize(limit)//查多少条
.get();
// 4) 得到查询的结果
SearchHits hits = searchResponse.getHits();
// 5) 取查询结果的总记录数
System.out.println("查询结果总记录数:" + hits.getTotalHits());
// 6) 取查询结果列表
Iterator<SearchHit> iterator = hits.iterator();
while (iterator.hasNext()){
SearchHit searchHit = iterator.next();
System.out.println(searchHit.getSourceAsString());//以json格式输出文档对象
Map<String, Object> source = searchHit.getSource();//文档对象
source.forEach((key,value)->{
System.out.println("key:"+key+"---value:"+value);
});
System.out.println("------------------>>>>>>>");
}
// 7) 关闭client
}
/***
* @Description:查询结果高亮显示
* (1) 高亮的配置
* 1) 设置高亮显示的域Term---字段
* 2) 设置高亮显示的前缀
* 3) 设置高亮显示的后缀
* (2) 在clent对象执行查询之前,设置高亮显示的信息
* (3) 便利结果列表时可以从结果中取高亮结果
* @Author: lqx
* @Date: 2020/5/17 18:53
* @param queryBuilder: 搜获方式,1.根据id搜索 2.根据Term查询 (关键字) 3.QueryString查询方式 (带分析的查询)
* @param page: 查询页码
* @param limit: 每页显示条数
* @param highlightFieldName: 高亮域的名字-相当于数据库表字段cloumn名
* @return: void
**/
public void searchQueryBuilderByLimitAndHighlight(QueryBuilder queryBuilder,int page,int limit,String highlightFieldName){
//高亮的配置--这里对title这个域进行高亮设置
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.field(highlightFieldName);//设置域--相当于数据库表字段
highlightBuilder.preTags("<em>");//设置前缀-与后缀得配对为一个标签
highlightBuilder.postTags("</em>");//设置后缀-与前缀得配对为一个标签
// 3)使用client执行查询
SearchResponse searchResponse = client.prepareSearch("index_hello")//索引库--类型
.setTypes("hello")//即数据库--表
.setQuery(queryBuilder)
.setFrom((page-1)*limit)//从index第几条开始,和mysql limit一样是从0开始的
.setSize(limit)//查多少条
.highlighter(highlightBuilder)//设置高亮信息
.get();//client对象执行
// 4) 得到查询的结果
SearchHits hits = searchResponse.getHits();
// 5) 取查询结果的总记录数
System.out.println("查询结果总记录数:" + hits.getTotalHits());
// 6) 取查询结果列表
Iterator<SearchHit> iterator = hits.iterator();
while (iterator.hasNext()){
SearchHit searchHit = iterator.next();
System.out.println(searchHit.getSourceAsString());//以json格式输出文档对象
Map<String, Object> source = searchHit.getSource();//文档对象
source.forEach((key,value)->{
System.out.println("key:"+key+"---value:"+value);
});
//如果有域设置了高亮,取高亮结果看看
Map<String, HighlightField> highlightFields = searchHit.getHighlightFields();
System.out.println("高亮结果--》》"+highlightBuilder);
highlightFields.forEach((key,highlightField)->{
if(highlightField!=null){
Text[] fragments = highlightField.fragments();
for(int i=0;i<fragments.length;i++){
System.out.println("这条记录的所有高亮域的值是---"+fragments[i]);
}
}
});
System.out.println("------------------>>>>>>>");
}
// 7) 关闭client
}
//关闭客户端client
@After
public void closeClient(){
if(client!=null){
client.close();
}
}
}