ElasticSearch
实际使用的场景:
1.在海量数据中,使用Mysql进行模糊查询,效率太低,且%在前不走索引
2.在日常场景中要求如果关键词不准确也可以搜索想要的效果
3.将搜索的关键词标明
ElasticSearch
提供存储、检索、分析功能
使用java语言的并且基于Lucene编写的搜索引擎,提供了分布式的全文索索功能。
分布式:主要为了突出横向扩展的能力
全文检索:将一段词语进行分词,并将分出的单次统一放入分词库中,在搜索时,根据关键词去分词库中检索,找到匹配的内容。(倒排索引)
ES:提供了一个统一的基于Restful风格的WEB接口,只需要发送一个HTTP请求,并且根据请求方式的不同,携带参数执行相应的功能
倒排索引
ES服务:将数据进行分词,存放入分词库中,建立索引
当客户端进行检索的时候,
1.query:根据关键词去分词库中检索内容
2.fetch:根据去分词库中检索到的id,直接拉取指定的数据
3.相关性比较
相关概念
Index 索引 相当于MySql中的database
Type 类型 相当于MySql中的Table(6.0以前)
Document 文档(json) 相当于MySql中的记录
Filed 属性 相当于MySql中的列名
相关操作:
增加操作:
1.put 增加、修改操作。必须指定id,因此通常修改
2.post 增加操作 不指定id,自动生成ID,会不断的增加
有id会修改id对应的数据,同时新增版本号
Put具有幂等性,post没有幂等性
查询数据:
1.get 获取 索引/type/id
用于并发控制,乐观锁,根据序列号进行CAS:
_seq_no 序列号
_primary_term
更新:
- post 索引/type/id/_update
“doc”:{
}
与元数据对比,相同版本号version,seq_no不增加
不带update和doc则会增加版本号
2.put也类似
删除文档:
Delete 索引/type/id
批量导入 POST 索引/type/_bulk
{“index”:{"_id":“1”}} action,id
{“name”:“Hoe”} 具体内容
操作ES
1、复杂检索
ES支持两种基本检索方式:
1.REST request URI请求 发送检索参数(URI+检索参数)
GET bank/_search?q=*&sort=account_number:asc
动作 索引/操作?请求所有&属性排序规则
2.REST request body发送(uri+请求体)
Query DSL
GET bank/_search
{
"query":{"match_all":{} //查询规则
},
"sort":[
{
"account_number":"asc" //排序规则
}
],
"from":5,
"size":5,
"_source":["balance","first_name"] //返回部分列
}
2.全文检索 match
GET bank/_search
{
"query":{
"match":{
"address":"Kings"
} //查询规则,模糊查询,倒排索引
}
}
短语匹配,匹配完整短语
GET bank/_search
{
"query":{
"match_phrase":{
"address":"mill lane"
} //必须匹配完整短语,不进行分词
}
}
多字段匹配
GET bank/_search
{
"query":{
"multi_match":{
"query":"mill" ,
"fields":["address","city"]
} //任意field包含query的条件,进行分词
}
}
bool复合查询
GET bank/_search
{
"query":{
"bool":{
"must":[
{"match":{
"gender":"F",
}},
{"match":{
"address":"mill",
}}
],//两个条件必须满足
"must_not":[
{"match":{
"age":"38",
}},
],//必须不满足
"should":[
{"match":{
"lastname":"wallace",
}}
]//应该匹配
}
}
}
结果过滤filter , 不会进行相关性得分
GET /bank/_search
{
"query": {
"bool": {
"must": { "match_all": {} },
"filter": {
"range": {
"balance": {
"gte": 20000,
"lte": 30000
}
}
}
}
}
}
3.执行聚合
提供分组和提取数据的能力
GET bank/_search
{
"query":{
"match":{"address":"mill"}
} ,
"aggs":{//按年龄进行聚合
"ageAgg":{
"term":{
"field":"age",
"size":10
}
}
}
}
IK分词器
es中标准分析器:analyzer:standard 这个词解析
中文分词:IK分词器
放入es中plugins目录–插件
测试:
分词器:
POST _analyze
{
"analyzer":"ik_max_word",
"text":"我是中国人"
}
自定义扩展词库
1.新建项目,ik向项目中发送请求
2.nginx,ik分词器向nginx发送请求
在IK中配置远程扩展字典
整合JAVA
java操作es
链接es
9200端口:HTTP
发送请求,Elasticseach-Rest-Clinet,封装es操作
高阶RestClient
public static RestHighLevelClient getClient(){
HttpHost httpHost = new HttpHost("192.168.1.100",9200);
RestClientBuilder clientBuilder = RestClient.builder(httpHost);
RestHighLevelClient client = new RestHighLevelClient(clientBuilder);
return client;
}
检索数据
IndexRequest indexRequest = new IndexRequest("users");
indexRequest.id("1");
// indexRequest.source("username", "zhangsan", "age", 18, "gender", "男");
User user = new User();
String jsonString = JSON.toJSONString(user);
indexRequest.source(jsonString, XContentType.JSON);
IndexResponse index = client.index(indexRequest,...)
复杂检索
//1.创建检索请求
SearchRequest searchRequest = new SearchRequest();
//指定索引
searchRequest.indices("bank");
//指定DSL,检索条件
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.matchQuery("address","mill"));
// searchSourceBuilder.from();
// searchSourceBuilder.size();
//聚合-按年龄进行聚合
searchSourceBuilder.aggregation(AggregationBuilders.terms("ageAgg").field("age").size(10));
searchRequest.source(searchSourceBuilder);
//2.执行检索
SearchResponse searchResponse = client.search(searchRequest,...)
//3.分析结果
System.out.println(searchResponse.toString());
组合查询
按关键词
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
if (!StringUtils.isEmpty(关键词)) {
boolQueryBuilder.must(QueryBuilders.matchQuery("title",关键词));
}
分析结果–封装成指定的格式:
//获取命中记录
SearchHits hits = response.getHits();
//总记录数
long total = hits.getTotalHits().value;
//每一条记录
for (SearchHit hit : hits.getHits()) {
String sourceString = hit.getSourceAsString();
JSON.parseObject()//解析成类保存进行显示
}