Elasticsearch研究结果分享
前言
经过前前后后将近4天左右的研究,做一下研究后的成果总结。分享给大家Elasticsearch的版本有很多,不同版本对应的语法有所不同。本人最开始是使用linux安装,遇到了不少坑,后面终于找到一个安装成功的案列。
软件安装
Elasticsearch安装:
Elasticsearch head插件(界面展示数据)安装:
后面由于寻找java使用Elasticsearch的资料时,发现不同版本的写法不同,由于资料有限,最后换了一个版本,linux安装修改以上链接教程中的版本号即可。本人现在暂时安装在windows上进行测试。
Elasticsearch版本:v6.3.2
Elasticsearch-IK中文分词插件版本:V6.3.2 (ik版本最好与Elasticsearch版本一致)
学习历程
关于Elasticsearch学习,我稍微说下我的步骤,仅供大家参考。
- 我首先是查看了一本Elasticsearch技术解析与实战的pdf书籍,了解基础的Elasticsearch的背景,基本信息,一些理论上的知识;
- 进行软件,以及相关插件的安装,测试软件是否能使用;
- 因为他提供restful接口,所以在postman上进行一些简单Elasticsearch的增删查改,可以很快的直观的感受Elasticsearch;
- 做一些复杂的postman上的查询请求,感受全文检索的功能;
- 查询java的使用,做简单的增删查改。
详细资料
详细资料我会发一个postman的文件和一个java工具类给大家。
下面我粘贴几个复杂的请求相关参数到文档中。
根据Type精确搜索,name全文检索搜索,查询条件如下:
{"query":{"bool":{"must":[{"match":{"name":"篮球"}},{"term":{"type":"服装类"}}]}}}根据Type精确搜索,name或者detail全文检索查询条件如下:
(对应大致sql【Where (Name 全文检索 ‘篮球’or detail 全文检索 ‘篮球’) and type =’服装’】)
{"query":{"bool":{"must":[{"bool":{"should":[{"match":{"name":"篮球"}},{"match_phrase":{"detail":"篮球"}}]}},{"term":{"type":"服装"}}]}}}-
Postman请求截图
简单增删查改工具类
import cn.com.header.rap.elasticsearch.entity.Product;
import com.header.extract.word.util.DateUtil;
import org.apache.http.HttpHost;
import org.elasticsearch.ElasticsearchStatusException;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.MultiSearchRequestBuilder;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.ScoreSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.*;
/**
* @author YuanYifeng
* @description: TODO
* @date 2019/5/28 17:03
*/
public class ElasticUtils {
// 相当于数据库名称
private static String indexName = "esdata";
// 初始化api客户端
public static RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost("175.102.179.67", 9200, "http")
));
/**
* 根据type精确搜索,name全文检索搜索
* @param type
* @param keyword
* @param start
* @param count
* @return
* @throws IOException
*/
public static List<Map<String, Object>> search(String type, String keyword, int start, int count) throws IOException {
//大致对应条件sql 为 Where type =’服装’and fieldName 全文检索 fieldName
SearchRequest searchRequest = new SearchRequest(indexName);
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
//bool多条件匹配
BoolQueryBuilder boolQueryBuilder=new BoolQueryBuilder();
//关键字匹配
TermQueryBuilder termQueryBuilder=new TermQueryBuilder("type","服装类");
//全文检索匹配对应字段
MatchQueryBuilder matchQueryBuilder = new MatchQueryBuilder("name", keyword);
//将多个条件加到bool匹配中
boolQueryBuilder.must(matchQueryBuilder);
boolQueryBuilder.must(termQueryBuilder);
sourceBuilder.query(boolQueryBuilder);
//第几页
sourceBuilder.from(start);
//第几条
sourceBuilder.size(count);
searchRequest.source(sourceBuilder);
searchRequest.types(type);
//匹配度从高到低
sourceBuilder.sort(new ScoreSortBuilder().order(SortOrder.DESC));
//执行查询
SearchResponse searchResponse = client.search(searchRequest);
SearchHits hits = searchResponse.getHits();
List<Map<String, Object>> matchRsult = new LinkedList<Map<String, Object>>();
for (SearchHit hit : hits.getHits())
{
matchRsult.add(hit.getSourceAsMap());
}
return matchRsult;
}
/**
* 复杂查询
* @param start
* @param count
* @return
* @throws IOException
*/
public static List<Map<String, Object>> searchDiff(int start, int count) throws IOException {
//大致对应条件sql 为 Where type =’服装’and (name 全文检索 ‘篮球’ or detail 全文检索 ‘篮球’)
SearchRequest searchRequest = new SearchRequest(indexName);
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
//bool多条件匹配
BoolQueryBuilder boolQueryBuilder=new BoolQueryBuilder();
//should条件 类似于or
BoolQueryBuilder boolShouldQueryBuilder=new BoolQueryBuilder();
boolShouldQueryBuilder.should(new MatchQueryBuilder("name", "篮球"));
boolShouldQueryBuilder.should(new MatchQueryBuilder("detail", "篮球"));
//将should条件加到bool匹配中
boolQueryBuilder.must(boolShouldQueryBuilder);
//将term条件加到bool匹配中,TermQueryBuilder类似于sql中的 "=" 条件
boolQueryBuilder.must(new TermQueryBuilder("type","服装"));
sourceBuilder.query(boolQueryBuilder);
//第几页
sourceBuilder.from(start);
//第几条
sourceBuilder.size(count);
searchRequest.source(sourceBuilder);
searchRequest.types("product");
//匹配度从高到低
sourceBuilder.sort(new ScoreSortBuilder().order(SortOrder.DESC));
//执行查询
SearchResponse searchResponse = client.search(searchRequest);
SearchHits hits = searchResponse.getHits();
List<Map<String, Object>> matchRsult = new LinkedList<Map<String, Object>>();
for (SearchHit hit : hits.getHits())
{
matchRsult.add(hit.getSourceAsMap());
}
return matchRsult;
}
/**
* 删除文档
* @param object
* @throws IOException
*/
public static void deleteDocument(Product object) throws IOException {
DeleteRequest deleteRequest = new DeleteRequest (indexName,"product", ((Product) object).getId());
System.out.println("已经从ElasticSearch服务器上删除id="+((Product) object).getId()+"的product文档");
client.delete(deleteRequest);
}
/**
* 获得指定type指定id的数据 json
* @param type
* @param id
* @return
* @throws IOException
*/
public static Map<String,Object> getDocument(String type,String id) throws IOException {
// TODO Auto-generated method stub
GetRequest request = new GetRequest(
indexName,
type,
id);
GetResponse response = client.get(request);
if(!response.isExists()){
System.out.println("检查到服务器上 "+type+" id="+id+ "的文档不存在");
return null;
}
else{
String source = response.getSourceAsString();
System.out.print("获取到服务器上 "+type+" id="+id+ "的文档内容是:");
System.out.println(source);
return response.getSourceAsMap();
}
}
/**
* 批量插入
* @param products
* @throws Exception
*/
public static void batchInsert(List<Product> products) throws Exception {
// TODO Auto-generated method stub
BulkRequest request = new BulkRequest();
for (Product product : products) {
Map<String,Object> map= objectToMap(product);
map.put("createdDt", DateUtil.formatDateTime(new Date()));
IndexRequest indexRequest= new IndexRequest(indexName, "product", product.getId()).source(map);
request.add(indexRequest);
}
client.bulk(request);
System.out.println("批量插入完成");
}
/**
* 插入数据
* @param object
* @throws IOException
*/
public static void addDocument(Product object) throws IOException {
Map<String, Object> jsonMap = new HashMap<>();
jsonMap.put("id", object.getId());
jsonMap.put("name", object.getName());
jsonMap.put("price", object.getPrice());
jsonMap.put("detail", object.getDetail());
jsonMap.put("type", object.getType());
//ES中日期类型插入时要转为约定格式的字符串
jsonMap.put("createdDt", DateUtil.formatDateTime(new Date()));
IndexRequest indexRequest = new IndexRequest(indexName, "product", object.getId())
.source(jsonMap);
client.index(indexRequest);
System.out.println("已经向ElasticSearch服务器增加Product:"+object);
}
/**
* 更新数据
* @param object
* @throws IOException
*/
public static void updateDocument(Product object) throws IOException {
if(object instanceof Product){
UpdateRequest updateRequest = new UpdateRequest (indexName, "product", ((Product) object).getId());
if(object.getDetail()!=null){
updateRequest.doc("detail",object.getDetail());
}
client.update(updateRequest);
System.out.println("已经在ElasticSearch服务器修改产品为:"+object);
}
}
private static boolean checkExistIndex(String indexName) throws IOException {
boolean result =true;
try {
OpenIndexRequest openIndexRequest = new OpenIndexRequest(indexName);
client.indices().open(openIndexRequest).isAcknowledged();
} catch (ElasticsearchStatusException ex) {
String m = "Elasticsearch exception [type=index_not_found_exception, reason=no such index]";
if (m.equals(ex.getMessage())) {
result = false;
}
}
if(result)
System.out.println("索引:" +indexName + " 是存在的");
else
System.out.println("索引:" +indexName + " 不存在");
return result;
}
/**
* 删除整个索引
* @param indexName
* @throws IOException
*/
private static void deleteIndex(String indexName) throws IOException {
DeleteIndexRequest request = new DeleteIndexRequest(indexName);
client.indices().delete(request);
System.out.println("删除了索引:"+indexName);
}
private static void createIndex(String indexName) throws IOException {
// TODO Auto-generated method stub
CreateIndexRequest request = new CreateIndexRequest(indexName);
client.indices().create(request);
System.out.println("创建了索引:"+indexName);
}
public static String getIndexName() {
return indexName;
}
public static void setIndexName(String indexName) {
ElasticUtils.indexName = indexName;
}
public static RestHighLevelClient getClient() {
return client;
}
public static void setClient(RestHighLevelClient client) {
ElasticUtils.client = client;
}
private static Map<String, Object> objectToMap(Object obj) throws Exception {
if (obj == null) {
return null;
}
Map<String, Object> map = new HashMap<String, Object>();
Field[] declaredFields = obj.getClass().getDeclaredFields();
for (Field field : declaredFields) {
field.setAccessible(true);
map.put(field.getName(), field.get(obj));
}
return map;
}
}
- 对应maven仓库
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>6.3.2</version>
</dependency>