spring-data-elasticsearch中常用的查询api使用和对比

负一、 repository

可以通过继承Repository的方式去快速的实现查询操作
官方文档里面有写

https://docs.spring.io/spring-data/elasticsearch/docs/current/reference/html/#elasticsearch.repositories

通过表格中字段的拼接去定义一个方法,就可以进行查询,实在是很方便,所以我这里就没写关于Repository的内容。
在这里插入图片描述

零 、ES搬砖总共分几步

模板类我使用的是:

	@Autowired
	ElasticsearchRestTemplate template;

核心使用的类有

  • Query

  • NativeQuery

  • QueryBuilder

  • QueryBuilders

大部分的操作基本就是 上边四个类,使用方法 分为三步

  • template.search(query)
  • query=new NativeQuery(queryBuilder)
  • queryBulder=QueryBuilder.xxxxBuilder();

会了这三步,基本就都会了,全剧终,再见~











正文

我们假设我们es中有一些手机的商品数据,我现在想要进行一些查询,然后看看查询结果,对比一下api的使用的区别。

java侧有一个产品类EsProduct,我们要使用的字段是name、和subTitle,可以看到都是text类型,且经过ik分词了
es侧有个手机名称叫 【华为 HUAWEI P20】

@Data
@EqualsAndHashCode(callSuper = false)
@Document(indexName = "pms",type="product",shards = 1,replicas = 0)
public class EsProduct implements Serializable {
    private static final long serialVersionUID = -1L;
    @Id

    private Long id;
    @Field(type = FieldType.Keyword)
    private String productSn;
    private Long brandId;
    @Field(type = FieldType.Keyword)
    private String brandName;//品牌
    private Long productCategoryId;
    @Field(type = FieldType.Keyword)
    private String productCategoryName;//产品类别名称
    private String pic;
    @Field(analyzer = "ik_max_word",type = FieldType.Text)
    private String name;
    @Field(analyzer = "ik_max_word",type = FieldType.Text)
    private String subTitle;
    @Field(analyzer = "ik_max_word",type = FieldType.Text)
    private String keywords;
    private BigDecimal price;
    private Integer sale;
    private Integer newStatus;
    private Integer recommandStatus;
    private Integer stock;
    private Integer promotionType;
    private Integer sort;
    @Field(type =FieldType.Nested)
    private List<EsProductAttributeValue> attrValueList;
}

一、match 与term

1、举个栗子一

首先写了一个get方法,传入相关的手机名称

   @GetMapping("/search1/{name}")
    public void search1(@PathVariable("name") String name) {
        Query query = null;
        QueryBuilder queryBuilder = null;

        queryBuilder = QueryBuilders.matchQuery("name", name);

        query = new NativeSearchQuery(queryBuilder);
        SearchHits<EsProduct> search = template.search(query, EsProduct.class);
    }

结果:

  • 1.当输入华为、或华为哥哥时,就可以搜索到华为手机
  • 2.如果输入华,就搜索不到,因为es中 ‘华为’ 分词后 并没有分解成‘华’ 和‘为’,却仍然是 ‘华为’,所以搜索不到
    结论
  • 1.matchQuery 是指 对name进行分词,成为数组 arr1[a,b…],然后分别将a,b…与es数据中的name属性的索引去对比,只要有一个对比上了,就算符合。
  • 2.举例:如果name属性不是keyword类型时,会被分词为【华为, HUAWEI, P20,P,20】,当输入华为哥哥时,会分词为【华为,哥哥】,可以看到两个数组 的 【华为】匹配到了,所以最终可以查到 华为手机。
  • 3.如果输入【华】、【为华】,就不能查到。原因如上
  • 另外说一下,可在kibana中,自己分词查一下:例如:
    在这里插入图片描述

2、举个栗子二

  @GetMapping("/search2/{name}")
    @ApiOperation("通过name查询名字中带有name的数据 term query(短语查询)")
    public void search2(@PathVariable("name") String name) {
        Query query = null;
        QueryBuilder queryBuilder = null;
        queryBuilder = QueryBuilders.termQuery("name", name);
        query = new NativeSearchQuery(queryBuilder);
        SearchHits<EsProduct> search = template.search(query, EsProduct.class);
    }

结果:

  • 输入 华为,可以搜索到
  • 输入 华 ,失败
  • 输入 华为哥哥,搜索不到

结论

  • 1.term 查询与上述match查询的区别在于,match查询时会将 输入的name进行分词,只有分词数组中有一个匹配到了es中的索引,就算搜索成功。term 与之相反,不对 输入的name进行分词

二、match query与fuzzy query

1.举个栗子一

结合结论看栗子

 @GetMapping("/search3/{name}")
    @ApiOperation("通过name查询名字中带有name的数据 match query 与fuzzy query(模糊查询)")
    public void search3(@PathVariable("name") String name) {
        Query query = null;
        QueryBuilder queryBuilder = null;
        queryBuilder = QueryBuilders.fuzzyQuery("name", name).fuzziness(Fuzziness.ONE);
        query = new NativeSearchQuery(queryBuilder);
    }

总结

  • 1.match query时携带模糊查询,首先 输入的name 会被分词,.fuzziness参数会指定编辑次数,fuzziness.zone 为绝对匹配,fuzziness.one为编辑一次

  • fuzziness.two为编辑两次。fuzziness.auto 为默认推荐的方式

    这篇文章讲的有挺好(https://www.jianshu.com/p/06f43b537a29)

  • 编辑一次指:

  • 1.将一个字符替换成另一个字符

  • 2.插入一个字符

  • 3.删除一个字符

  • 4.两个字符进行位置交换(莱文斯坦距离【Levenshtein distance】算法中 视之为两次编辑,而【Damerau–Levenshtein distance】视为一次编辑【默认是这种算法】)


  • 一.结合上方栗子,在fuzzyQuery(“name”,name)后添加fuzziness参数 如下:
queryBuilder= QueryBuilders.matchQuery("name",name).fuzziness(Fuzziness.ONE);
  • 1、输入华为哥,分词后变成【华为、哥】,但是因为是match查询,所有不需要模糊也能搜索到华为
    • 但是上述分词中还有【哥】,所以可视之 为删除掉,变成了 空字符串,所以除了华为之外,还可以匹配到其他的数据
  • 2、输入华为哥哥,分词后变成【华为、哥哥】,华为手机依然能搜索到。
    • 但是【哥哥】这个分词无论加一个字符、删字符、变化位置,都不能与其他索引匹配,所以最终只能查到华为手机

  • 二、结合上方栗子,继续添加.prefixLength(1)参数,表示在term级别上至少要匹配1个字符后才能进行上述的编辑,如下:
    queryBuilder= QueryBuilders.matchQuery("name",name).fuzziness(Fuzziness.ONE).prefixLength(1);
    
  • 1.输入华为哥,分词后为【华为、哥】,【华为】可以匹配到华为手机
    • 但是这回哥字就不能删除了,必要要和其他索引匹配1个字符后才能开始编辑,所以最终只能匹配到华为手机

  • 三、结合上方栗子,添加transpostion(true|false),true(默认)时为Damerau–Levenshtein distance,false为莱文斯坦-距离算法

    	 queryBuilder= QueryBuilders.matchQuery("name",name).fuzziness(Fuzziness.ONE).fuzzyTranspositions(true);
    
    • 1.输入: 为华,分词为【‘为’,‘华‘】,这样编辑一次,就可以删除掉,所有匹配的是所有的数据
    • 2.使用fuzzyQuery进行查询,如下:
      queryBuilder=QueryBuilders.fuzzyQuery("name",name).fuzziness(Fuzziness.ONE);;
      
      • 输入: 为华,因为fuzzyQuery是 不会对需要检索的内容进行分词,所以term级别的短语是【为华】,所以编辑一次时,会将 这两个字进行调换,最终查到的是华为手机

三、query 和filter

query会计算相关度从而得到score,filter是从query的结果中进行筛选,不进行score的计算

     /**
     * 通过关键字-keyword去匹配字段【name,subTitle】
     */
    @GetMapping("/search4")
    @ApiOperation("在商品名称和描述中查询,品牌名称和种类进行筛选【根据商品价格进行排序】")
    public voidsearch4(@RequestParam(required = false) String brandName,
                          @RequestParam(required = false) String productCategoryName,
                          @RequestParam(required = false) String keyword) {

        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();


        //keyword 匹配 name 或 subTitle
        if (StringUtils.isEmpty(keyword)) {
            //如果没有输入关键字,就匹配所有 
            nativeSearchQueryBuilder.withQuery(QueryBuilders.matchAllQuery());
        } else {
            BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
            boolQueryBuilder.should().add(QueryBuilders.matchQuery("name", keyword));
            boolQueryBuilder.should().add(QueryBuilders.matchQuery("subTitle", keyword));
            nativeSearchQueryBuilder.withQuery(boolQueryBuilder);
        }

        //过滤 品牌和种类
        BoolQueryBuilder filter = QueryBuilders.boolQuery();
        if (!StringUtils.isEmpty(brandName)) {
            filter.must().add(QueryBuilders.termQuery("brandName", brandName));
        }
        if (!StringUtils.isEmpty(productCategoryName)) {
            filter.must().add(QueryBuilders.termQuery("productCategoryName", productCategoryName));
        }

        //page 分页
        nativeSearchQueryBuilder.withPageable(PageRequest.of(1,2));
        //sort 根据价格进行排序
        nativeSearchQueryBuilder.withSort(SortBuilders.fieldSort("price"));

        String result = "";
        nativeSearchQueryBuilder.withFilter(filter);
        NativeSearchQuery query = nativeSearchQueryBuilder.build();
    }

说一下我对es的dsl的学习方法,一方面看官方文档外,其实我最喜欢的方式是通过spring-data-elasticsearch提供的template去一一尝试各个方法,debug代码,把DSL复制出来,然后放到kibana中运行,就可以自己创造样例去学习了,如下图这般

在这里插入图片描述

四、boost

QueryBuilder对象后接.boost(float),会将该query的score * boost所设置的值

 @GetMapping("/search5")
    @ApiOperation("name查询,name 优先显示,分数不够,乘法来凑")
    public void search5(@RequestParam(required = false) String keyword) {

        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();

        //keyword 匹配 name 或 subTitle
        if (StringUtils.isEmpty(keyword)) {
            nativeSearchQueryBuilder.withQuery(QueryBuilders.matchAllQuery());
        } else {
            BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

            boolQueryBuilder.should().add(QueryBuilders.matchQuery("name", keyword).boost(2));
            boolQueryBuilder.should().add(QueryBuilders.matchQuery("subTitle", keyword));
            nativeSearchQueryBuilder.withQuery(boolQueryBuilder);
        }
        NativeSearchQuery query = nativeSearchQueryBuilder.build();
        SearchHits<EsProduct> search = template.search(query, EsProduct.class);
        

结论

  • 该方法的目的是在 手机的名称 或 描述中查找 【华为】(注意是或),如果手机的名称中就带有华为,那就把分数×2。目的是优先显示名字有关键字的数据。

五、function_score

我们创建一个查询,一般都是通过QueryBuilders,现在要说的是 其下的functionScoreQuery方法,这个方法就是用于处理和自定义分数有关的操作


  • 首先看一下他的五种重构,实际上 就是两种
    在这里插入图片描述

其一:ScoreFunctionBuilder function

(不妨直接理解字面意思:分数方法 的构建器)


  • 该对象 通过 建造者 ScoreFunctionBuilders来创建 一个 分数方法的构建器

  • 都可以创建什么种类的呢?

  • 1.可以让他们按照我给的权重来判分 weightFactorFunction( 权重乘法 ) ,例:ScoreFunctionBuilders.weightFactorFunction(2); 将权重变成 2

  • 2.可以让他们先按默认的算分,然后再乘上 我给的某个数值类型的字段fieldValueFactorFunction

    • 例如:按销售量算分。
    • 问:那如果销售量太大算出来的分有点太大怎么办?
    • 答:可以乘以一个倍数啊,比如 *0.001 ,代码上的实现就是 .factor(float)
    • 问:乘以倍数 也是线性的放大或缩小,我想不要线性的,我想要对数类型的曲线变化怎么办?
    • 答:也可以作答啊,代码上实现就是.modifier(Modifier.log)
    • 问:本来我的分数是0,log O=NAN啊,因为10的n次方中,n等于多少时 都不可能计算得到0的,那怎么办
    • 答:可以使用modifiler.log1p 或者log2p啊
    • 问:为什么刚才乘上字段的值,而不是加上字段的值,或者取平均数啊,可以做到么?
    • 答:默认是做乘法,但也可以你想要的计算操作。不过不是在 FunctionScoreQueryBuilder(其父类也不能设置)中设置,而是再querybuilder中设置
    • 例子:
    FieldValueFactorFunctionBuilder price = ScoreFunctionBuilders.fieldValueFactorFunction("price").modifier(FieldValueFactorFunction.Modifier.LOG);
    FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery(price);
    functionScoreQueryBuilder.boostMode(CombineFunction.SUM) ---看这句 ,不就实现了么
    
  • 3.可以让他们按0-1随机给分吧 ,那就选用 randomFunction

  • 4.还有其他方法可以自己看看吧,有一些与地址位置相关的。


其二: filterFunctionBuilder

  • A:(仔细看) 我们不忘初心,回到起点,最初我们只是 想要调动 QueryBuilders.functionScoreQuery() 进行一个查询啊,

  • B: 是啊,然后我们传入了 一个scoreFunctionBuilder啊,有什么问题么?

  • A: 你刚才设置了几次权重?

  • B: 设置了一次,设置为2 啊!

  • A: 嗯,你说的没问题,那我再问你,你刚才操作了几个字段?

  • B: 操作了一个字段

  • A: 那我现在想操作多个字段,设置不同的权重怎么办

  • B: 呃…这有什么意义

  • A: 比如我想做一个查询,我是大众点评软件,想查询 ‘水煮鱼’后,显示 销量高,评分高,然后是有wifi

    • 显然销量和评分都很重要,但是我们软件呢 是良心软件,更注重评分,评分高的自然要排在推荐的最上边
    • 不过也有可能有人恶意的去给低分,
    • 那么如果销量很高时,我们也可以不太注重评分,从而将他排在前边。
    • 最后是wifi了,有的话,当然好了,没有的话,也不太重要。
    • 好了,以上情景给出来了。显然评分最重要,销量次之,最后是wifi,我们可以先看看 这几个参数的数值对比,
    • 假设有两家店都直接叫‘水煮鱼’,和我的搜索完美契合,就假设这样算出的分是1分的话,评分最多是5分,
    • 销量可能是成百上千,wifi是有或无,那么从最简单的来,我们就设置wifi的权重是1分吧。
    	FunctionScoreQueryBuilder.FilterFunctionBuilder wifi=
         new FunctionScoreQueryBuilder.FilterFunctionBuilder
          (
           QueryBuilders.termQuery("wifi","有"),ScoreFunctionBuilders.weightFactorFunction(1);//查询wifi 为有,设置权重为1
         );
    
    
    • 评分呢…就算五分吧
    FunctionScoreQueryBuilder.FilterFunctionBuilder grade=
     new FunctionScoreQueryBuilder.FilterFunctionBuilder
     (
    	 ScoreFunctionBuilders.fieldValueFactorFunction("grade")
     );
    
  • B:等等!我记得这默认是乘法吧,听你刚才的意思,好像我们要用加法的!~~

  • A:是的!,别急嘛!follow me~~~
    * 最后是销量了…,我打开了大众点评一看,销售都是按月售的,基本最多的是几千条吧,那我们就用log1p吧,如果10的3次是1千,4次方 是1万,
    * 也就是说如果销量了 1千-1万之间的话,就能得3分,好像并不能有效区分啊,那我们还是除以1000吧,这样就相当于 1000的销量可以媲美 评分1分。

    FunctionScoreQueryBuilder.FilterFunctionBuilder sales=new FunctionScoreQueryBuilder.FilterFunctionBuilder(
    	 ScoreFunctionBuilders.fieldValueFactorFunction("sales").factor(0.001f)
    )
    
  • A: 好,我们最后都弄完了,最终得到了三个对象 wifi,grade,sales 都是 FunctionScoreQueryBuilder.FilterFunctionBuilder 类型的
    * 接下来放到一个数组中
    * FunctionScoreQueryBuilder.FilterFunctionBuilder[] arr=new FunctionScoreQueryBuilder.FilterFunctionBuilder[3];
    * 不忘初心!我们写出我们最开始要干的事:最一个自定义的分数查询:
    * QueryBuilders.functionScoreQuery()
    * 将arr 作为参数参入进去 QueryBuilders.functionScoreQuery(arr);

  • B:刚才说好的 三个得分要相加呢

  • A: 哦,差点忘了

    queryBuilder= QueryBuilders.functionScoreQuery(arr).boostMode(CombineFunction.SUM)
    

    简单练习

    /**
         *  接下来简单练习一下:
         * 还有一种用法是: 我现在是大学招生办的人,现在开始筛选学生的志愿。
         * 学生呢,有编号为1,2,3 的三个志愿可填写。可重复填写(三个志愿都写的我们学校),我们学校呢 想招生100个人。
         * 对于第一志愿 就选我们学校的人,我们特别重视,第二志愿次之,第三志愿再次之,如果三个志愿都填写的我们学校,那这样的人我们最喜欢
         * 除此之外呢,我们要学生的分数要超过670分才能被招生进来
         *
         * 好,情景为以上信息。
         *   1.先找到 分数大于670分的人
         *   2.我们分别在三个志愿中查询,三个志愿的权重分别是 10,5,2 ,且最少有一个志愿填写了我们学校。
         *   3.只要前100名
    
     //分数要大于670
        RangeQueryBuilder score = QueryBuilders.rangeQuery("score").gt(670);
    
        FunctionScoreQueryBuilder.FilterFunctionBuilder[] arr = new FunctionScoreQueryBuilder.FilterFunctionBuilder[3];
        String schoolName = "哈哈大学";
    
        FunctionScoreQueryBuilder.FilterFunctionBuilder voluntary1 = new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.termQuery("voluntary1", schoolName), ScoreFunctionBuilders.weightFactorFunction(10));
        FunctionScoreQueryBuilder.FilterFunctionBuilder voluntary2 = new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.termQuery("voluntary2", schoolName), ScoreFunctionBuilders.weightFactorFunction(10));
        FunctionScoreQueryBuilder.FilterFunctionBuilder voluntary3 = new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.termQuery("voluntary3", schoolName), ScoreFunctionBuilders.weightFactorFunction(10));
        arr[0] = voluntary1;
        arr[1] = voluntary2;
        arr[2] = voluntary3;
        FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery(score, arr);
        Query query = new NativeSearchQueryBuilder().withQuery(functionScoreQueryBuilder).withPageable(PageRequest.of(0,100)).build();
        template.search(query, Student.class);
    

回到 重载方法

上方两种方式 都额外还有一种重载方法,就是增加了一个queryBuilder的参数。那有什么区别呢。


你可以创建一个普通的queyBulder测试一下

   @GetMapping("/search9")
    public void search9(String name) {
        FunctionScoreQueryBuilder.FilterFunctionBuilder[] arr = new FunctionScoreQueryBuilder.FilterFunctionBuilder[2];

        FunctionScoreQueryBuilder.FilterFunctionBuilder item1 =
                new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.matchQuery("name", name),
                        ScoreFunctionBuilders.weightFactorFunction(10));
        FunctionScoreQueryBuilder.FilterFunctionBuilder item2 =
                new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.matchQuery("subTitle", name),
                        ScoreFunctionBuilders.weightFactorFunction(5));
        arr[0] = item1;
        arr[1] = item2;

        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.should().add(QueryBuilders.matchQuery("name", name));
        boolQueryBuilder.should().add(QueryBuilders.matchQuery("subTitle", name));
        //有查询,在查询结果后 对分数进行filter
        FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery(boolQueryBuilder, arr).scoreMode(FunctionScoreQuery.ScoreMode.SUM);

        Query query = new NativeSearchQueryBuilder().withQuery(functionScoreQueryBuilder).build();
        SearchHits<EsProduct> search = template.search(query, EsProduct.class);
        print(search);
    }

然后和上述一样传入方法中,然后debug看一下 DSL
可以发现,加入query查询的DSL 会先match查询,然后再用function_score去计算分数,而反之不加入query查询的,在query阶段会直接matchALL

加了query查询

{
  "function_score" : {
    "query" : {
      "bool" : {
        "should" : [ 加了query 的会进行查询
          {
            "match" : {
              "name" : {
                "query" : "手机",
                "operator" : "OR",
                "prefix_length" : 0,
                "max_expansions" : 50,
                "fuzzy_transpositions" : true,
                "lenient" : false,
                "zero_terms_query" : "NONE",
                "auto_generate_synonyms_phrase_query" : true,
                "boost" : 1.0
              }
            }
          },
          {
            "match" : {
              "subTitle" : {
                "query" : "手机",
                "operator" : "OR",
                "prefix_length" : 0,
                "max_expansions" : 50,
                "fuzzy_transpositions" : true,
                "lenient" : false,
                "zero_terms_query" : "NONE",
                "auto_generate_synonyms_phrase_query" : true,
                "boost" : 1.0
              }
            }
          }
        ],
        "adjust_pure_negative" : true,
        "boost" : 1.0
      }
    },
    "functions" : [
      {
        "filter" : {
          "match" : {
            "name" : {
              "query" : "手机",
              "operator" : "OR",
              "prefix_length" : 0,
              "max_expansions" : 50,
              "fuzzy_transpositions" : true,
              "lenient" : false,
              "zero_terms_query" : "NONE",
              "auto_generate_synonyms_phrase_query" : true,
              "boost" : 1.0
            }
          }
        },
        "weight" : 10.0
      },
      {
        "filter" : {
          "match" : {
            "subTitle" : {
              "query" : "手机",
              "operator" : "OR",
              "prefix_length" : 0,
              "max_expansions" : 50,
              "fuzzy_transpositions" : true,
              "lenient" : false,
              "zero_terms_query" : "NONE",
              "auto_generate_synonyms_phrase_query" : true,
              "boost" : 1.0
            }
          }
        },
        "weight" : 5.0
      }
    ],
    "score_mode" : "sum",
    "max_boost" : 3.4028235E38,
    "boost" : 1.0
  }
}

不加query查询

{
  "function_score" : {
    "query" : {
      "match_all" : { 不加query的会直接match_all
        "boost" : 1.0
      }
    },
    "functions" : [
      {
        "filter" : {
          "match" : {
            "name" : {
              "query" : "手机",
              "operator" : "OR",
              "prefix_length" : 0,
              "max_expansions" : 50,
              "fuzzy_transpositions" : true,
              "lenient" : false,
              "zero_terms_query" : "NONE",
              "auto_generate_synonyms_phrase_query" : true,
              "boost" : 1.0
            }
          }
        },
        "weight" : 10.0
      },
      {
        "filter" : {
          "match" : {
            "subTitle" : {
              "query" : "手机",
              "operator" : "OR",
              "prefix_length" : 0,
              "max_expansions" : 50,
              "fuzzy_transpositions" : true,
              "lenient" : false,
              "zero_terms_query" : "NONE",
              "auto_generate_synonyms_phrase_query" : true,
              "boost" : 1.0
            }
          }
        },
        "weight" : 5.0
      }
    ],
    "score_mode" : "sum",
    "max_boost" : 3.4028235E38,
    "min_score" : 5.0,
    "boost" : 1.0
  }
}
  • 5
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
spring-boot-starter-data-elasticsearch8是一个用于在Spring Boot应用集成Elasticsearch的starter包。它提供了一组简化的API和配置,使得在应用使用Elasticsearch进行数据存储和检索变得更加方便。 在该starter包,模糊查询可以通过使用Elasticsearch的QueryBuilders来实现。QueryBuilders是Elasticsearch提供的一个构建查询的工具类,可以用于构建各种类型的查询条件。 要实现模糊查询,可以使用QueryBuilders提供的模糊查询方法之一,比如fuzzyQuery()。该方法可以根据指定的字段和模糊度来进行模糊查询。以下是一个示例代码: ```java import org.elasticsearch.index.query.QueryBuilders; import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate; import org.springframework.data.elasticsearch.core.query.NativeSearchQuery; import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; // 创建NativeSearchQueryBuilder对象 NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder(); // 添加模糊查询条件 queryBuilder.withQuery(QueryBuilders.fuzzyQuery("fieldName", "keyword")); // 创建NativeSearchQuery对象 NativeSearchQuery searchQuery = queryBuilder.build(); // 执行查询 List<YourEntity> results = elasticsearchRestTemplate.queryForList(searchQuery, YourEntity.class); ``` 在上述代码,我们使用了NativeSearchQueryBuilder来构建查询条件,然后使用ElasticsearchRestTemplate执行查询。其,"fieldName"是要进行模糊查询的字段名,"keyword"是要查询的关键词。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值