简介
概括
elasticsearch是一个基于Lucene的高扩展的分布式搜索服务器,支持开箱即用,隐藏了Lucene的复杂性,对外提供Restful 接口来操作索引、搜索。
优势:
1.扩展性好,可部署上百台服务器集群,处理PB级数据。
2.近实时的去索引数据、搜索数据。
逻辑结构
1、将要搜索的文档内容分词,所有不重复的词组成分词 列表。
2、将搜索的文档最终以Document方式存储起来。
3、每个词和docment都有关联。
概念
took:本次操作花费的时间,单位为毫秒。
timed_out:请求是否超时
_shards:说明本次操作共搜索了哪些分片
hits:搜索命中的记录
hits.total : 符合条件的文档总数 hits.hits :匹配度较高的前N个文档
hits.max_score:文档匹配得分,这里为最高分
_score:每个文档都有一个匹配度得分,按照降序排 列。
_source:显示了文档的原始内容。
使用
1.安装ElasticSearch(配置yml)
cluster.name: heqinag //集群名称
node.name: heqiang_1 //节点名称
network.host: 0.0.0.0 //主机地址
http.port: 9200 //运行端口号
transport.tcp.port: 9300 //节点端口
node.master: true //是否主节点
node.data: true //是否可存数据
discovery.zen.minimum_master_nodes: 1
bootstrap.memory_lock: false
node.max_local_storage_nodes: 1
# discovery.zen.ping.unicast.hosts: {"0.0.0.0:9300","0.0.0.0:9301","0.0.0.0:9302"} //其他节点地址
path.data: D:\develop\search\elasticsearch-6.2.1\data //索引存放目录
path.logs: D:\develop\search\elasticsearch-6.2.1\logs //日志存放目录
http.cors.enabled: true //允许跨域
http.cors.allow-origin: /.*/
2.安装ES可视化管理插件header(谷歌插件)
3.创建索引库(相当于数据库,指定类型相当于表)
方式1:
PUT localhost:9200/索引库名称
{
"settings":{
"index":{
"number_of_shards":1, //分片数量
"number_of_replicas":0 //副本数量
}
}
}
4.创建映射(可使用Java代码实现)
Post localhost:9200/索引库名称/doc/_mapping
{
"properties" : {
"description" : {
"type" : "text"
},
"name" : {
"type" : "text"
},
"studymodel" : {
"type" : "keyword"
}
}
}
GET localhost:9200/索引库名称/doc/_mapping(查看)
5.添加文档(可使用Java代码实现)
POST localhost:9200/heqiang/doc/qaeTWnEB5aBC1lRt3B7i(id可不写,自动生成)
{
"name" : "如梦令",
"description" :"昨夜雨疏风骤,浓睡不消残酒,试问卷帘人,却道海棠依旧,知否,知否,应是绿肥红瘦",
"studymodel" : "123"
}
6.搜索服务
GET localhost:9200/heqiang/doc/{id}
GET localhost:9200/heqiang/doc/_search?q=name:"如梦"
映射维护
添加映射: POST 请求:http://localhost:9200/索引库名称/doc/_mapping
{
“properties”: {
“pic”: {
“type”: “keyword”,
“index”: “false”
},
“description”: {
“type”: “text”,
“search_analyzer”: “ik_smart”,
“analyzer”: “ik_max_word”
},
“name”: {
“type”: “text”,
“search_analyzer”: “ik_smart”,
“analyzer”: “ik_max_word”
},
“time”: {
“type”: “date”,
“format”: “yyyy-MM-dd HH-mm-ss||yyyy-MM-dd”
}
}
}
删除映射: 通过删除索引来删除映射
更新映射: 映射创建成功可以添加新字段,已有字段不允许更新
查询映射:GET: http://localhost:9200/_search
JavaAPI代码维护步骤
1.添加坐标
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>6.2.1</version>
</dependency>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>6.2.1</version>
</dependency>
2.定义配置类用于创建bean
@Configuration
public class ElasticsearchConfig {
@Value("${xuecheng.elasticsearch.hostlist}")
private String hostlist;
@Bean
public RestHighLevelClient restHighLevelClient(){
//解析hostlist配置信息
String[] split = hostlist.split(",");
//创建HttpHost数组,其中存放es主机和端口的配置信息
HttpHost[] httpHostArray = new HttpHost[split.length];
for(int i=0;i<split.length;i++){
String item = split[i];
httpHostArray[i] = new HttpHost(item.split(":")[0], Integer.parseInt(item.split(":")[1]), "http");
}
//创建RestHighLevelClient客户端
return new RestHighLevelClient(RestClient.builder(httpHostArray));
}
//项目主要使用RestHighLevelClient,对于低级的客户端暂时不用
@Bean
public RestClient restClient(){
//解析hostlist配置信息
String[] split = hostlist.split(",");
//创建HttpHost数组,其中存放es主机和端口的配置信息
HttpHost[] httpHostArray = new HttpHost[split.length];
for(int i=0;i<split.length;i++){
String item = split[i];
httpHostArray[i] = new HttpHost(item.split(":")[0], Integer.parseInt(item.split(":")[1]), "http");
}
return RestClient.builder(httpHostArray).build();
}
}
3.删除索引库
@Test
public void testDeleteIndex() throws IOException {
//删除索引对象
DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest("test");
//操作索引的客户端
IndicesClient indices = client.indices();
//执行删除索引
DeleteIndexResponse delete = indices.delete(deleteIndexRequest);
//得到响应
boolean acknowledged = delete.isAcknowledged();
System.out.println(acknowledged);
}
4.部分更新文档
@Test
public void testUpadate() throws IOException {
UpdateRequest updateRequest = new UpdateRequest("xc_course", "doc", "tzk2-mUBGsEnDOUe482B");
Map map = new HashMap<>();
map.put("name", "小生不才");
updateRequest.doc(map);
UpdateResponse updateResponse = client.update(updateRequest);
RestStatus status = updateResponse.status();
System.out.println(status);
}
DSL查询(代码实现)
DSL(Domain Specific Language)是ES提出的基于json的搜索方式,在搜索时传入特定的json格式的数据来完成不同的搜索需求。
@Test
public void testSearchPage() throws IOException, ParseException {
//搜索请求对象
SearchRequest searchRequest = new SearchRequest("heqiang");
//指定类型
searchRequest.types("doc");
//搜索源构建对象
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//设置分页参数
//页码
int page = 1;
//每页记录数
int size = 1;
//计算出记录起始下标
int from = (page-1)*size;
searchSourceBuilder.from(from);//起始记录下标,从0开始
searchSourceBuilder.size(size);//每页显示的记录数
//搜索方式(重点代码)
//matchAllQuery搜索全部
searchSourceBuilder.query(QueryBuilders.matchAllQuery());
//设置源字段过虑,第一个参数结果集包括哪些字段,第二个参数表示结果集不包括哪些字段
searchSourceBuilder.fetchSource(new String[]{"name","studymodel","price","description"},new String[]{});
//向搜索请求对象中设置搜索源
searchRequest.source(searchSourceBuilder);
//执行搜索,向ES发起http请求
SearchResponse searchResponse = client.search(searchRequest);
//搜索结果
SearchHits hits = searchResponse.getHits();
//匹配到的总记录数
long totalHits = hits.getTotalHits();
//得到匹配度高的文档
SearchHit[] searchHits = hits.getHits();
//日期格式化对象
//SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy‐MM‐dd HH:mm:ss");
for(SearchHit hit:searchHits){
//文档的主键
String id = hit.getId();
//源文档内容
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
String name = (String) sourceAsMap.get("name");
//前边设置了源文档字段过虑,这里(timestamp)是取不到的
String description = (String) sourceAsMap.get("description");
//学习模式
String studymodel = (String) sourceAsMap.get("studymodel");
//价格
Double price = (Double) sourceAsMap.get("price");
//日期
//Date timestamp = dateFormat.parse((String)sourceAsMap.get("timestamp"));
System.out.println(name);
System.out.println(studymodel);
System.out.println(description);
}
}
Term Query为精确查询,在搜索时会整体匹配关键字,不再将关键字分词。
searchSourceBuilder.query(QueryBuilders.termQuery("name","查询内容"));
Terms Query根据id精确匹配
//定义ids
String[] ids = new String[]{"1","2"};
searchSourceBuilder.query(QueryBuilders.termsQuery("_id",ids));
match Query即全文检索,先将搜索字符串分词,再使用各各词条从索引中搜索
//MatchQuery只能匹配一个字段
searchSourceBuilder.query(QueryBuilders.matchQuery("description", "spring开发框架")
.minimumShouldMatch("80%"));
//如果是三个词匹配,3*0.8=2.4,向上取整2,至少匹配两个词
//不写匹配任意一个即可
multi Query增加权重boost
searchSourceBuilder.query(QueryBuilders.multiMatchQuery("spring css", "name", "description")
.minimumShouldMatch("50%")
.field("name", 10));
布尔查询
//boolQuery搜索方式
//先定义一个MultiMatchQuery
MultiMatchQueryBuilder multiMatchQueryBuilder =QueryBuilders.multiMatchQuery("spring css", "name","description")
.minimumShouldMatch("50%")
.field("name", 10);
//再定义一个termQuery
TermQueryBuilder termQueryBuilder =QueryBuilders.termQuery("studymodel", "201001");
//定义一个boolQuery
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
boolQueryBuilder.must(multiMatchQueryBuilder);
boolQueryBuilder.must(termQueryBuilder);
过滤器
//先定义一个MultiMatchQuery
MultiMatchQueryBuilder multiMatchQueryBuilder =QueryBuilders.multiMatchQuery("spring css", "name","description")
.minimumShouldMatch("50%")
.field("name", 10);
//定义一个boolQuery
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
boolQueryBuilder.must(multiMatchQueryBuilder);
//定义过虑器
boolQueryBuilder.filter(QueryBuilders.termQuery("studymodel","201001"));
boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte(9).lte(100));
searchSourceBuilder.query(boolQueryBuilder);
排序
//添加排序
searchSourceBuilder.sort("studymodel", SortOrder.DESC);
searchSourceBuilder.sort("price", SortOrder.ASC);
高亮显示
//设置高亮
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.preTags("<font class='eslight'>");
highlightBuilder.postTags("</font>");
//设置高亮字段
highlightBuilder.fields().add(newHighlightBuilder.Field("name"));
searchSourceBuilder.highlighter(highlightBuilder);
如有疑问或不同见解,欢迎留言共同交流,博主看到后会在第一时间回复哦…