一、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分词器安装避坑
安装流程链接:

如果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%";
    }