Easy-Es Easy-Es
💋首页
  • v3.0.0(当前版本)
  • What's New

    • What' s New In Easy-Es v3.0.0?
  • 历史版本

    • v1.x.x
    • v2.x.x
  • 升级指南

    • 升级到3.x.x说明
💖赞助
  • 开源社区
  • 周边好物
  • 项目PPT (opens new window)
  • 项目介绍
  • 项目成员
  • 参与贡献
加入社区讨论
谁在使用
  • Doc-Apis (opens new window)
  • 健身计划一键生成系统 (opens new window)
  • 极氪汽车
  • Vuepress-theme-vdoing (opens new window)
  • Gitee (opens new window)
  • GitCode (opens new window)
  • Github (opens new window)
  • 简体中文 (opens new window)
  • English (opens new window)

广告采用随机轮播方式显示 ❤️成为赞助商
💋首页
  • v3.0.0(当前版本)
  • What's New

    • What' s New In Easy-Es v3.0.0?
  • 历史版本

    • v1.x.x
    • v2.x.x
  • 升级指南

    • 升级到3.x.x说明
💖赞助
  • 开源社区
  • 周边好物
  • 项目PPT (opens new window)
  • 项目介绍
  • 项目成员
  • 参与贡献
加入社区讨论
谁在使用
  • Doc-Apis (opens new window)
  • 健身计划一键生成系统 (opens new window)
  • 极氪汽车
  • Vuepress-theme-vdoing (opens new window)
  • Gitee (opens new window)
  • GitCode (opens new window)
  • Github (opens new window)
  • 简体中文 (opens new window)
  • English (opens new window)
  • 快速入门

    • 简介
    • 适用场景
    • 顾虑粉碎
    • 避坑指南
    • 快速开始
    • springboot集成demo
    • spring集成指南
    • solon集成指南
    • 配置
    • 注解
  • 核心功能

    • 条件构造器

      • 条件构造器介绍
      • 索引条件构造器
      • 查询条件构造器
      • 更新条件构造器
    • 索引CRUD

      • 索引托管模式
      • 索引CRUD
    • 数据CRUD

      • 数据同步方案
      • 数据CRUD
    • 多数据源支持
    • 动态索引支持
    • 四大嵌套查询
    • 链式调用
  • 拓展功能

    • 混合查询
    • 原生查询
    • 分页查询
    • 嵌套类型
    • Join父子类型
    • 获取DSL语句
    • 执行DSL语句
    • 执行SQL语句
    • 自定义RequestOptions
    • 自定义default方法
  • 高阶语法

    • 查询字段过滤
    • 排序
    • 聚合查询
    • 分词&模糊匹配
      • 分词匹配相关功能API
      • 模糊匹配相关功能API
      • 查询API及字段索引类型参考
      • 代码示例
      • queryString 妙用
    • 权重
    • 高亮查询
    • GEO地理位置查询
    • IP查询
  • 插件

    • 插件
    • 领域模型生成插件
  • 其它

    • 问答
    • 与MP差异
    • MySQL和EE语法对比
    • 更新日志
    • 更新计划
    • 版权
    • 鸣谢
  • v2.x文档
  • 高阶语法
老汉
2023-03-18
目录

分词&模糊匹配

# 分词匹配相关功能API

match(boolean condition, R column, Object val);
matchPhase(boolean condition, R column, Object val, Float boost);
matchAllQuery();
matchPhrasePrefixQuery(boolean condition, R column, Object val, int maxExpansions, Float boost);
multiMatchQuery(boolean condition, Object val, Operator operator, int minimumShouldMatch, Float boost, R... columns);
queryStringQuery(boolean condition, String queryString, Float boost);
prefixQuery(boolean condition, R column, String prefix, Float boost);
1
2
3
4
5
6
7

注意

注意:涉及需要分词匹配的字段索引类型必须为text或keyword_text(不指定时默认为此类型),并为其指定分词器,所需分词器需提前安装,否则将使用es默认分词器,对中文支持不好.

# 模糊匹配相关功能API

// 注意 like底层对应es的wildcard查询,传入的值会被默认拼接上*号通配符 例如 *老汉*
like(boolean condition, String column, Object val, Float boost);
// likeLeft会在值左侧拼接通配符* 例如 *老汉
likeLeft(boolean condition, String column, Object val, Float boost);
// likeRight会在值右侧拼接通配符* 例如老汉*
likeRight(boolean condition, String column, Object val, Float boost);
1
2
3
4
5
6

# 查询API及字段索引类型参考

关于如何选择使用上述API以及如何正确建立对应索引,不了解ES的同学可以参考下表:

ES原生 Easy-Es keyword类型 text类型 是否支持分词
term eq 完全匹配 查询条件必须都是text分词中的,且不能多余,多个分词时必须连续,顺序不能颠倒 否
wildcard like/likeLeft/likeRight 根据api模糊匹配 like全模糊,likeLeft左模糊,likeRight右模糊 不支持 否
match match 完全匹配 match分词结果和text的分词结果有相同的即可,不考虑顺序 是
matchPhrase matchPhrase 完全匹配 matchPhrase的分词结果必须在text字段分词中都包含且顺序必须都相同,而且必须都是连续的. 是
matchPhrasePrefixQuery matchPhrasePrefixQuery 不支持 matchPhrasePrefix与matchPhrase相同,除了它允许在文本的最后一个词上的前缀匹配. 是
multiMatchQuery multiMatchQuery 完全匹配 全字段分词匹配,可实现全文检索功能 是
queryStringQuery queryStringQuery 完全匹配 queryString中的分词结果至少有一个在text字段的分词结果中,不考虑顺序 是
prefixQuery prefixQuery 完全匹配 只要分词后的词条中有词条满足前缀条件即可 是
  • 分词匹配
  • 例: match("content", "老王")--->content 包含关键词 '老王' 如果分词粒度设置的比较细,老王可能会被拆分成"老"和"王",只要content中包含"老"或"王",均可以被搜出来,其它api可参考下面代码示例.

# 代码示例


    @Test
    public void testMatch(){
        // 会对输入做分词,只要所有分词中有一个词在内容中有匹配就会查询出该数据,无视分词顺序
        LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();
        wrapper.match(Document::getContent,"技术");
        List<Document> documents = documentMapper.selectList(wrapper);
        System.out.println(documents.size());
    }    

    @Test
    public void testMatchPhrase() {
        // 会对输入做分词,但是需要结果中也包含所有的分词,而且顺序要求一样,否则就无法查询出结果
        // 例如es中数据是 技术过硬,如果搜索关键词为过硬技术就无法查询出结果
        LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();
        wrapper.matchPhrase(Document::getContent, "技术");
        List<Document> documents = documentMapper.selectList(wrapper);
        System.out.println(documents);
    }

    @Test
    public void testMatchAllQuery() {
        // 查询所有数据,类似mysql select all.
        LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();
        wrapper.matchAllQuery();
        List<Document> documents = documentMapper.selectList(wrapper);
        System.out.println(documents);
    }

    @Test
    public void testMatchPhrasePrefixQuery() {
        // 前缀匹配查询 查询字符串的最后一个词才能当作前缀使用
        // 前缀 可能会匹配成千上万的词,这不仅会消耗很多系统资源,而且结果的用处也不大,所以可以提供入参maxExpansions,若不写则默认为50
        LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();
        wrapper.matchPhrasePrefixQuery(Document::getCustomField, "乌拉巴拉", 10);
        List<Document> documents = documentMapper.selectList(wrapper);
        System.out.println(documents);
    }

    @Test
    public void testMultiMatchQuery() {
        // 从多个指定字段中查询包含老王的数据
        LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();
        wrapper.multiMatchQuery("老王", Document::getTitle, Document::getContent, Document::getCreator, Document::getCustomField);

        // 其中,默认的Operator为OR,默认的minShouldMatch为60% 这两个参数都可以按需调整,我们api是支持的 例如:
        // 其中AND意味着所有搜索的Token都必须被匹配,OR表示只要有一个Token匹配即可. minShouldMatch 80 表示只查询匹配度大于80%的数据
        // wrapper.multiMatchQuery("老王",Operator.AND,80,Document::getCustomField,Document::getContent);

        List<Document> documents = documentMapper.selectList(wrapper);
        System.out.println(documents.size());
        System.out.println(documents);
    }

    @Test
    public void queryStringQuery() {
        // 从所有字段中查询包含关键词老汉的数据
        LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();
        wrapper.queryStringQuery("老汉");
        List<Document> documents = documentMapper.selectList(wrapper);
        System.out.println(documents);
    }

    @Test
    public void prefixQuery() {
        // 查询创建者以"隔壁"打头的所有数据  比如隔壁老王 隔壁老汉 都能被查出来
        LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();
        wrapper.prefixQuery(Document::getCreator, "隔壁");
        List<Document> documents = documentMapper.selectList(wrapper);
        System.out.println(documents);
    }

    @Test
    public void like() {
            // 等价于MySQL中 like %汉推% 像老汉推...就可以被查出来
            LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();
            wrapper.like(Document::getTitle, "汉推");
            List<Document> documents = documentMapper.selectList(wrapper);
            System.out.println(documents);
    }

    @Test
    public void likeLeft() {
            // 等价于MySQL中 like %汉 像老汉就可以被查出来
            LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();
            wrapper.likeLeft(Document::getTitle, "汉");
            List<Document> documents = documentMapper.selectList(wrapper);
            System.out.println(documents);
    }

    @Test
    public void likeRight() {
            // 等价于MySQL中 like 老%  像老汉就可以被查出来
            LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();
            wrapper.likeRight(Document::getTitle, "老");
            List<Document> documents = documentMapper.selectList(wrapper);
            System.out.println(documents);
    }
    
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99

# queryString 妙用

由于queryString可以检索keyword和text两种类型,所以有一部分使用场景是如下图这样的,所有查询字段,查询类型,匹配规则等都是不固定的,由用户自由来选,这种情况下,您除了可以使用我们提供的四大嵌套查询中的or()来实现,还可以通过queryStringQuery API来解决.

image1

我们可以用StringBuilder把查询字段和值拼接进去,组装成最终的查询语句. 以上图为例,我演示一个场景,请忽略场景合理性,因为是我瞎xx选的:假设我的查询条件是:字段:创建者 等于老王,且创建者分词匹配"隔壁"(比如:隔壁老汉,隔壁老王),或者创建者包含大猪蹄子,对应的代码如下:

    @Test
    public void testQueryString() {
        LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();
        StringBuilder sb = new StringBuilder();
        sb.append("(")
                .append("(")
                .append("creator.keyword")
                .append(":")
                .append("老王")
                .append(")")
                .append("AND")
                .append("(")
                .append("creator")
                .append(":")
                .append("隔壁")
                .append(")")
                .append(")")
                .append("OR")
                .append("(")
                .append("creator.keyword")
                .append(":")
                .append("*大猪蹄子*")
                .append(")");
        // sb最终拼接为:((creator.keyword:老王)AND(creator:隔壁))OR(creator.keyword:*大猪蹄子*) ,可以说和MySQL语法非常相似了
        wrapper.queryStringQuery(sb.toString());
        List<Document> documents = documentMapper.selectList(wrapper);
        System.out.println(documents);
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

前端参数页面每传递一行查询参数,我们往sb中append对应参数就完事了,是不是很简单,没错,但是代码不优雅,可咋整? 老汉已经给你们想好出路了,我们提供了工具类,其全路径为:cn.easyes.core.toolkit.QueryUtils 我们用使用该工具类重构上面的代码,如下:

    @Test
    public void testQueryStringQueryMulti() {
        LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();
        String queryStr = QueryUtils.combine(Link.OR,
                QueryUtils.buildQueryString(Document::getCreator, "老王", Query.EQ, Link.AND),
                QueryUtils.buildQueryString(Document::getCreator, "隔壁", Query.MATCH))
                + QueryUtils.buildQueryString(Document::getCreator, "*大猪蹄子*", Query.EQ);
        wrapper.queryStringQuery(queryStr);
        List<Document> documents = documentMapper.selectList(wrapper);
        System.out.println(documents);
    }
1
2
3
4
5
6
7
8
9
10
11

是不是优雅了很多,其中的枚举Query和Link我也已经为你们封装好了,直接使用即可,不懂其枚举含义也可以直接点开查看,我在源码中有详细注释.

帮助我们改善此文档 (opens new window)
上次更新: 2025/05/11
聚合查询
权重

← 聚合查询 权重→

Theme by Vdoing | Copyright © 2021-2025 老汉 | 浙ICP备2022020479号 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式