一、Elasticsearch 7.2.0 安装步骤
1.1 下载 Elasticsearch 7.2.0
https://www.elastic.co/cn/downloads/past-releases/elasticsearch-7-2-0
1.2 解压安装
我的是window版,下载完后,ES 文件目录结构如下图所示:
bin :脚本文件,包括 ES 启动 & 安装插件等等
config : elasticsearch.yml(ES 配置文件)、jvm.options(JVM 配置文件)、日志配置文件等等
JDK : 内置的 JDK,JAVA_VERSION=“12.0.1”
lib : 类库
logs : 日志文件
modules : ES 所有模块,包括 X-pack 等
plugins : ES 已经安装的插件。默认没有插件 (也是放ik分词器目录)
data : ES 启动的时候,会有该目录,用来存储文档数据。该目录可以设置
1.3 启动 Elasticsearch
文件bin目录,双击 elasticsearch.bat 即可
1.4 验证是否启动成功
浏览器输入: http://localhost:9200/ ,然后可以得到下面的信息:
{
"name" : "........",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "..........",
"version" : {
"number" : "7.2.0",
"build_flavor" : "default",
"build_type" : "zip",
"build_hash" : "508c38a",
"build_date" : "2019-06-20T15:54:18.811730Z",
"build_snapshot" : false,
"lucene_version" : "8.0.0",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
},
"tagline" : "You Know, for Search"
}
二、ElasticSearch7.2.0 IK分词器安装
2.1 下载地址:
https://github.com/medcl/elasticsearch-analysis-ik/releases/tag/v7.2.0
2.2 Ik分词器安装避坑
安装流程链接:
https://blog.csdn.net/u014082714/article/details/89963046
如果IK与ES版本不对应,运行ES时会报错说两者版本不对,导致无法启动。
注意:我下载了IK分词器表面是7.2.0版本的,得到的处理过后的zip解压开是7.0.0版本的,只需要修改你的路径下的pom里面的版本改成7.2.0即可。
<properties>
<elasticsearch.version>7.2.0</elasticsearch.version>
<maven.compiler.target>1.8</maven.compiler.target>
<elasticsearch.assembly.descriptor>${project.basedir}/src/main/assemblies/plugin.xml</elasticsearch.assembly.descriptor>
<elasticsearch.plugin.name>analysis-ik</elasticsearch.plugin.name>
<elasticsearch.plugin.classname>org.elasticsearch.plugin.analysis.ik.AnalysisIkPlugin</elasticsearch.plugin.classname>
<elasticsearch.plugin.jvm>true</elasticsearch.plugin.jvm>
<tests.rest.load_packaged>false</tests.rest.load_packaged>
<skip.unit.tests>true</skip.unit.tests>
<gpg.keyname>4E899B30</gpg.keyname>
<gpg.useagent>true</gpg.useagent>
</properties>
2.3 创建ik分词器文件夹
在你所安装es的所在目录下的的plugins下创建analysis-ik文件夹,我电脑的es下的\plugins目录即(D:\soft\elasticsearch-7.2.0\plugins)下新建analysis-ik文件夹.
然后将上面打的zip包拷贝到analysis-ik文件夹下并将zip压缩包解压到此.
2.4 重启
最后重新启动elasticsearch,可以启动说明安装成功,不需要修改Elasticsearch配置文件。
三、Elasticsearch 使用
关于 Elasticsearch 概念和api请参考官网或者此链接
https://www.kaifaxueyuan.com/server/elasticsearch7.html
3.1 添加pom引用
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.2.0</version>
</dependency>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>7.2.0</version>
</dependency>
3.2 application.yml配置:
spring:
data:
elasticsearch:
repositories:
enabled: true
cluster-nodes: 127.0.0.1:9300
3.3 创建索引方式
(1)添加新文档需要调用IndexRequest请求,可以直接传递json数据,如下:
IndexRequest request = new IndexRequest(“posts”); //索引
request.id(“1”); //文档id String jsonString = “{” +
““user”:“kimchy”,” +
““postDate”:“2013-01-30”,” +
““message”:“trying out Elasticsearch”” +
“}”; request.source(jsonString, XContentType.JSON); //以字符串形式提供的文档源
(2)也可以使用Map作为参数,如下
Map<String, Object> jsonMap = new HashMap<>(); jsonMap.put(“user”,
“kimchy”); jsonMap.put(“postDate”, new Date()); jsonMap.put(“message”,
“trying out Elasticsearch”); IndexRequest indexRequest = new
IndexRequest(“posts”)
.id(“1”).source(jsonMap); //以Map形式提供的文档源,可自动转换为JSON格式
(3)还可以使用XConttentBuilder构建内容。
XContentBuilder builder = XContentFactory.jsonBuilder();
builder.startObject(); {
builder.field(“user”, “kimchy”);
builder.timeField(“postDate”, new Date());
builder.field(“message”, “trying out Elasticsearch”); } builder.endObject(); IndexRequest indexRequest = new
IndexRequest(“posts”)
.id(“1”).source(builder);
(4)直接用键值对对象构架数据。
IndexRequest indexRequest = new IndexRequest(“posts”)
.id(“1”)
.source(“user”, “kimchy”,
“postDate”, new Date(),
“message”, “trying out Elasticsearch”);
3.4 search api
构造查询主要用到两个类:SearchRequest和SearchSourceBuilder。
SearchRequest searchRequest = new SearchRequest();
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();// 大多数的搜索参数被添加到 SearchSourceBuilder 。它为每个进入请求体的每个东西都提供 setter 方法。
searchSourceBuilder.query(QueryBuilders.matchAllQuery()); // 添加一个 match_all 查询到 searchSourceBuilder 。
searchRequest.source(searchSourceBuilder); //将searchSourceBuilder添加到searchRequest
searchRequest.indices("gets"); //设定索引
searchRequest.types("doc"); // 限制请求的类别
searchRequest.source(searchSourceBuilder); //将searchSourceBuilder添加到searchRequest
BoolQueryBuilder的使用
matchQuery与termQuery
matchQuery:会将搜索词分词,再与目标查询字段进行匹配,若分词中的任意一个词与目标字段匹配上,则可查询到。
termQuery:不会对搜索词进行分词处理,而是作为一个整体与目标字段进行匹配,若完全匹配,则可查询到。
//搜索全部文档
QueryBuilder queryBuilder = QueryBuilders.matchAllQuery();
//单个匹配,搜索name为jack的文档
queryBuilder = QueryBuilders.matchQuery("name", "jack");
//多个字段匹配某一个值
queryBuilder = QueryBuilders.multiMatchQuery("music", "name", "interest");//搜索name中或interest中包含有music的文档(必须与music一致)
//termQuery("key", obj) 完全匹配
queryBuilder = QueryBuilders.termsQuery("name", "jack");
queryBuilder = QueryBuilders.termsQuery("user", new ArrayList<String>().add("jack"));
//范围查询 价格大于100
queryBuilder = QueryBuilders.rangeQuery("price").lte(100);
//模糊查询,?匹配单个字符,*匹配多个字符
queryBuilder = QueryBuilders.wildcardQuery("name", "*jack*");//搜索名字中含有jack文档(name中只要包含jack即可)
BoolQueryBuilder进行复合查询
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
WildcardQueryBuilder queryBuilder1 = QueryBuilders.wildcardQuery("name", "*jack*");//搜索名字中含有jack的文档
WildcardQueryBuilder queryBuilder2 = QueryBuilders.wildcardQuery("interest", "*read*");//搜索interest中含有read的文档
//使用must (name中必须含有jack,interest中必须含有read,相当于and)
boolQueryBuilder.must(queryBuilder1);
boolQueryBuilder.must(queryBuilder2);
//使用should (name中含有jack或者interest含有read,相当于or)
boolQueryBuilder.should(queryBuilder1);
boolQueryBuilder.should(queryBuilder2);
//filter(返回的文档必须满足filter子句的条件,但是不会像must一样,参与计算分值)
设置匹配度
boost 参数被用来提升一个语句的相对权重( boost 值大于 1 )或降低相对权重( boost值处于 0 到 1 之间),
但是这种提升或降低并不是线性的,换句话说,如果一个 boost 值为 2 ,并不能获得两倍的评分 _score 。
minimumShouldMatch(只有某一行数据的fieldName字段的值中至少包括了minimumShouldMatch个term才会返回这一行数据,否则认为不命中)
// 包裹查询只返回一个常数分数等于提高每个文档的查询
QueryBuilders.constantScoreQuery(QueryBuilders.termQuery("name", "jack")).boost(2.0f);
//多个字段匹配某一个值 设置匹配度 ;
Map<String, Float> fieldsBoosts = new HashMap<>(2);
fieldsBoosts.put( WarehouseIndexKeyEnum.WAREHOUSE_NAME.getKey(), 9f);
fieldsBoosts.put( WarehouseIndexKeyEnum.ADDRESS.getKey(), 5f);
boolQueryBuilder.must(QueryBuilders.multiMatchQuery("jack").fields(fieldsBoosts).minimumShouldMatch("100%"));
分页
searchSourceBuilder.from(0);
searchSourceBuilder.size(10);
根据(ik)分词来设置匹配度
private String getMiniMumShouldMatch (String keyword) {
List<String> analyzeKeywords = new ArrayList<>();
try {
AnalyzeRequest analyzeRequest = new AnalyzeRequest("storage").tokenizer("ik_smart").text("我的名字是jack");
AnalyzeResponse response = restHighLevelClient.indices().analyze(analyzeRequest, RequestOptions.DEFAULT);
List<AnalyzeResponse.AnalyzeToken> tokens = response.getTokens();
for (AnalyzeResponse.AnalyzeToken token : tokens) {
analyzeKeywords.add(token.getTerm());
}
} catch (IOException e) {
logger.error("关键字分词异常, keyword:{}", keyword, e);
}
if (!CollectionUtils.isEmpty(keywords) && keywords.size() > 2) {
return "75%";
}
return "100%";
}