init docs

This commit is contained in:
xpc1024 2022-03-17 11:01:44 +08:00
parent fd14b3f9a4
commit 2da8b89e1e
168 changed files with 3548 additions and 0 deletions

1
CNAME Normal file
View File

@ -0,0 +1 @@
easy-es.cn

0
docs/.nojekyll Normal file
View File

3
docs/AbstractWrapper.md Normal file
View File

@ -0,0 +1,3 @@
> **说明:**
> QueryWrapper(LambdaEsQueryWrapper) 和 UpdateWrapper(LambdaEsUpdateWrapper) 的父类<br />用于生成 语句 的 where 条件, entity 属性也用于生成 语句 的 where 条件<br />注意: entity 生成的 where 条件与 使用各个 api 生成的 where 条件**没有任何关联行为**

1
docs/CNAME Normal file
View File

@ -0,0 +1 @@
easy-es.cn

3
docs/QueryWrapper.md Normal file
View File

@ -0,0 +1,3 @@
> **说明:**
> 继承自 AbstractWrapper ,自身的内部属性 entity 也用于生成 where 条件<br />及 LambdaEsQueryWrapper

61
docs/README.md Normal file
View File

@ -0,0 +1,61 @@
# 简介
Easy-Es简称EE是一款基于ElasticSearch(简称Es)官方提供的RestHighLevelClient打造的低码开发框架在 RestHighLevelClient 的基础上,只做增强不做改变,为简化开发、提高效率而生,您如果有用过Mybatis-Plus(简称MP),那么您基本可以零学习成本直接上手EE,EE是MP的Es平替版,同时也融入了更多Es独有的功能,助力您快速实现各种场景的开发.
> **理念** 把简单,易用,方便留给用户,把复杂留给框架.
> **愿景** 让天下没有难用的Es, 致力于成为全球最受欢迎的ElasticSearch搜索引擎开发框架.
# ![logo](https://iknow.hs.net/4f7ec0c1-ec40-47a6-9a69-8284cb6563a7.png)
## 优势
---
- **屏蔽语言差异**开发者只需要会MySQL语法即可使用Es,真正做到一通百通,无需学习枯燥易忘的Es语法,Es使用相对MySQL较低频,学了长期不用也会忘,没必要浪费这时间.开发就应该专注于业务,省下的时间去撸铁,去陪女朋友陪家人,不做资本家的韭菜
- **代码量极少:** 与直接使用RestHighLevelClient相比,相同的查询平均可以节省3-5倍左右的代码量
- **零魔法值:**字段名称直接从实体中获取,无需输入字段名称字符串这种魔法值,提高代码可读性,杜绝因字段名称修改而代码漏改带来的Bug
- **零额外学习成本**开发者只要会国内最受欢迎的Mybatis-Plus语法,即可无缝迁移至EE,EE采用和前者相同的语法,消除使用者额外学习成本,直接上手,爽
- **降低开发者门槛: **Es通常需要中高级开发者才能驾驭,但通过接入EE,即便是只了解ES基础的初学者也可以轻松驾驭ES完成绝大多数需求的开发,可以提高人员利用率,降低企业成本
## 特性
---
- **无侵入**:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
- **损耗小**:启动即会自动注入基本 CURD性能基本无损耗直接面向对象操作
- **强大的 CRUD 操作**:内置通用 Mapper仅仅通过少量配置即可实现大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
- **支持 Lambda 形式调用**:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错段
- **支持主键自动生成**支持2 种主键策略,可自由配置,完美解决主键问题
- **支持 ActiveRecord 模式**:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
- **支持自定义全局通用操作**:支持全局通用方法注入( Write once, use anywhere
- **内置分页插件**基于RestHighLevelClient 物理分页,开发者无需关心具体操作,且无需额外配置插件,写分页等同于普通 List 查询,且保持和PageHelper插件同样的分页返回字段,无需担心命名影响
- **MySQL功能全覆盖**:MySQL中支持的功能通过EE都可以轻松实现
- **支持ES高阶语法**:支持高亮搜索,分词查询,权重查询,聚合查询等高阶语法
- **良好的拓展性**:底层仍使用RestHighLevelClient,可保持其拓展性,开发者在使用EE的同时,仍可使用RestHighLevelClient的功能
...
## 框架结构
---
![EasyEsJG.jpg](https://iknow.hs.net/e8153631-2f74-427f-82c4-4f009099c62a.jpg)
## 代码托管
---
> [码云Gitee](https://gitee.com/easy-es/easy-es)✔ | [Github](https://github.com/xpc1024/easy-es)✔
## English Documentation
---
[Documentation-EN](https://www.yuque.com/laohan-14b9d/tald79/qf7ns2)
## 参与贡献
---
尽管目前Easy-Es还处于新生儿状态,但由于站在巨人的肩膀上(RestHighLevelClient和Mybatis-Plus),这是一款出道即巅峰的框架,这么说并不是说它写得有多好,而是它融合了两款目前非常优秀框架的优点,这决定了它起点的高度,未来可期,所以在此欢迎各路好汉一起来参与完善 Easy-Es我们期待你的 PR
- 贡献代码:代码地址 [Easy-ES](https://github.com/xpc1024/easy-es),欢迎提交 Issue 或者 Pull Requests
- 维护文档:文档地址 [Easy-ES](https://www.yuque.com/laohan-14b9d/tald79/qf7ns2),欢迎参与翻译和修订

3
docs/UpdateWrapper.md Normal file
View File

@ -0,0 +1,3 @@
> **说明:**
> 继承自 AbstractWrapper ,自身的内部属性 entity 也用于生成 where 条件<br />及 LambdaEsUpdateWrapper

9
docs/_coverpage.md Normal file
View File

@ -0,0 +1,9 @@
<!-- _coverpage.md -->
![logo](https://iknow.hs.net/dc1dbd9c-3c6d-463f-98c4-16d186c9ada3.png)
v0.9.6
本框架由 [**Gitee码云**](https://gitee.com/easy-es/easy-es) 提供金牌代码托管服务
> 更易用的ES搜索引擎框架 , 为简化开发而生!
[示例](demo.md)[快速开始](quick-start.md)

6
docs/_navbar.md Normal file
View File

@ -0,0 +1,6 @@
<!-- _navbar.md -->
* [首页](/)
* [联系](contact.md)
* 语言
* [English](/en/)
* [中文](/)

79
docs/_sidebar.md Normal file
View File

@ -0,0 +1,79 @@
- [简介](README.md)
- [适用场景](sceen.md)
- [顾虑粉碎](worry-free.md)
- [快速开始](quick-start.md)
- [Springboot集成Demo](demo.md)
- 核心功能
- [index索引](index.md)
- [是否存在索引](exists-index.md)
- [删除索引](del-index.md)
- [更新索引](update-index.md)
- [创建索引](create-index.md)
- [索引分片](index-shard.md)
- [索引别名](index-alias.md)
- CRUD接口
- [Select](select.md)
- [Update](update.md)
- [Delete](delete.md)
- [Insert](insert.md)
- [条件构造器](condition.md)
- [eq](eq.md)
- [ne](ne.md)
- [match](match.md)
- [gt](gt.md)
- [ge](ge.md)
- [lt](lt.md)
- [le](le.md)
- [between](between.md)
- [notBetween](notBetween.md)
- [like](like.md)
- [notLike](notLike.md)
- [likeLeft](likeLeft.md)
- [likeRight](likeRight.md)
- [isNull](isNull.md)
- [isNotNull](isNotNull.md)
- [in](in.md)
- [notIn](notIn.md)
- [groupBy](groupBy.md)
- [orderByAsc](orderByAsc.md)
- [orderByDesc](orderByDesc.md)
- [or](or.md)
- [and](and.md)
- [limit](limit.md)
- [from](from.md)
- [size](size.md)
- [set](set.md)
- [AbstractWrapper](AbstractWrapper.md)
- [QueryWrapper](QueryWrapper.md)
- [UpdateWrapper](UpdateWrapper.md)
- 拓展功能
- [混合查询](hybrid-query.md)
- [原生查询](origin-query.md)
- [source](source.md)
- [分页](page.md)
- 高阶语法
- [字段过滤](filter.md)
- [排序](sort.md)
- [聚合查询](aggregation.md)
- [分词查询](particple.md)
- [权重](weight.md)
- [高亮查询](highlight.md)
- [GEO地理位置查询](geo.md)
- [GeoBoundingBox](geo-bounding-box.md)
- [GeoDistance](geo-distance.md)
- [GeoPolygon](geo-ploygon.md)
- [GeoShape](geo-shape.md)
- 注解
- [索引注解](index-anno.md)
- [字段注解](field-anno.md)
- [主键注解](id-anno.md)
- [配置](config.md)
- [更新计划](update-plan.md)
- [更新日志](update-log.md)
- [FAQ](faq.md)
- [与MP差异](diff.md)
- [MySQL与Easy-Es语法对照表](compare.md)
- [捐赠支持](donate.md)
- [捐赠记录](donate-log.md)
- [版权](copyright.md)
- [鸣谢](thanks.md)

28
docs/aggregation.md Normal file
View File

@ -0,0 +1,28 @@
在MySQL中,我们可以通过指定字段进行group by聚合,EE同样也支持聚合:
```java
@Test
public void testGroupBy() throws IOException {
LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();
wrapper.likeRight(Document::getContent,"推");
wrapper.groupBy(Document::getCreator);
SearchResponse response = documentMapper.search(wrapper);
System.out.println(response);
}
```
> **Tips:**
> 尽管语法与MP一致,但实际上,ES的聚合结果是放在单独的对象中的,格式如下所示,因此我们高阶语法均需要用SearchResponse来接收返回结果,这点需要区别于MP和MySQL.
```json
"aggregations":{"sterms#creator":{"doc_count_error_upper_bound":0,"sum_other_doc_count":0,"buckets":[{"key":"老汉","doc_count":2},{"key":"老王","doc_count":1}]}}
```
其它聚合:
```json
// 求最小值
wrapper.min();
// 求最大值
wrapper.max();
// 求平均值
wrapper.avg();
// 求和
wrapper.sum();
```

7
docs/and.md Normal file
View File

@ -0,0 +1,7 @@
```java
and(Consumer<Param> consumer)
and(boolean condition, Consumer<Param> consumer)
```
- AND 嵌套
- 例: and(i -> i.eq(Document::getTitle, "Hello").ne(Document::getCreator, "Guy"))--->and (title ='Hello' and creator != 'Guy' )

7
docs/between.md Normal file
View File

@ -0,0 +1,7 @@
```java
between(R column, Object val1, Object val2)
between(boolean condition, R column, Object val1, Object val2)
```
- BETWEEN 值1 AND 值2
- 例: between("age", 18, 30)--->age between 18 and 30

33
docs/compare.md Normal file
View File

@ -0,0 +1,33 @@
| MySQL | Easy-Es |
| --- | --- |
| and | and |
| or | or |
| = | eq |
| != | ne |
| > | gt |
| >= | ge |
| < | lt |
| <= | le |
| like '%field%' | like |
| not like '%field%' | notLike |
| like '%field' | likeLeft |
| like 'field%' | likeRight |
| between | between |
| notBetween | notBetween |
| is null | isNull |
| is notNull | isNotNull |
| in | in |
| not in | notIn |
| group by | groupBy |
| order by | orderBy |
| min | min |
| max | max |
| avg | avg |
| sum | sum |
| sum | sum |
| - | orderByAsc |
| - | orderByDesc |
| - | match |
| - | highLight |
| ... | ... |

17
docs/condition.md Normal file
View File

@ -0,0 +1,17 @@
> **说明:**
> - 以下出现的第一个入参boolean condition表示该条件是否加入最后生成的语句中例如query.like(StringUtils.isNotBlank(name), Entity::getName, name) .eq(age!=null && age >= 0, Entity::getAge, age)
> - 以下代码块内的多个方法均为从上往下补全个别boolean类型的入参,默认为true
> - 以下出现的泛型Param均为Wrapper的子类实例(均具有AbstractWrapper的所有方法)
> - 以下方法在入参中出现的R为泛型,在普通wrapper中是String,在LambdaWrapper中是函数(例:Entity::getId,Entity为实体类,getId为字段id的getMethod)
> - 以下方法入参中的R column均表示数据库字段,当R具体类型为String时则为数据库字段名(字段名是数据库关键字的自己用转义符包裹!)!而不是实体类数据字段名!!!,另当R具体类型为SFunction时项目runtime不支持eclipse自家的编译器!!!
> - 以下举例均为使用普通wrapper,入参为Map和List的均以json形式表现!
> - 使用中如果入参的Map或者List为空,则不会加入最后生成的sql中!
> - 有任何疑问就点开源码看,看不懂函数的[点击我学习新知识](https://www.jianshu.com/p/613a6118e2e0)
> **警告:**
> 不支持以及不赞成在 RPC 调用中把 Wrapper 进行传输
> 1. wrapper 很重
> 1. 传输 wrapper 可以类比为你的 controller 用 map 接收值(开发一时爽,维护火葬场)
> 1. 正确的 RPC 调用姿势是写一个 DTO 进行传输,被调用方再根据 DTO 执行相应的操作
> 1. 我们拒绝接受任何关于 RPC 传输 Wrapper 报错相关的 issue 甚至 pr

43
docs/config.md Normal file
View File

@ -0,0 +1,43 @@
**基础配置:**<br />如果缺失可导致项目无法正常启动,其中账号密码可缺省.
```yaml
easy-es:
enable: true # 是否开启EE自动配置
address : 127.0.0.1:9200 # es连接地址+端口 格式必须为ip:port,如果是集群则可用逗号隔开
schema: http # 默认为http
username: elastic #如果无账号密码则可不配置此行
password: WG7WVmuNMtM4GwNYkyWH #如果无账号密码则可不配置此行
```
**拓展配置:**<br />可缺省,为了提高生产性能,你可以进一步配置(0.9.4+版本才支持)
```yaml
easy-es:
connectTimeout: 5000 # 连接超时时间 单位:ms
socketTimeout: 5000 # 通信超时时间 单位:ms
requestTimeout: 5000 # 请求超时时间 单位:ms
connectionRequestTimeout: 5000 # 连接请求超时时间 单位:ms
maxConnTotal: 100 # 最大连接数 单位:个
maxConnPerRoute: 100 # 最大连接路由数 单位:个
```
**全局配置:**<br />可缺省,不影响项目启动,若缺省则为默认值
```yaml
easy-es:
global-config:
db-config:
table-prefix: daily_ # 索引前缀,可用于区分环境 默认为空
id-type: auto # id生成策略 默认为auto
field-strategy: not_empty # 字段更新策略 默认为not_null
```
> **Tips:**
> - id-type支持2种类型:
>
auto: 由ES自动生成,是默认的配置,无需您额外配置 推荐
> uuid: 系统生成UUID,然后插入ES (不推荐)
> - field-strategy支持3种类型:
>
not_null: 非Null判断,字段值为非Null时,才会被更新
> not_empty: 非空判断,字段值为非空字符串时才会被更新
> ignore: 忽略判断,无论字段值为什么,都会被更新
> - 在配置了全局策略后,您仍可以通过注解针对个别类进行个性化配置,全局配置的优先级是小于注解配置的
>

15
docs/contact.md Normal file
View File

@ -0,0 +1,15 @@
坐标:杭州
开发5年全栈菜狗,健身8年肌肉猛男,欢迎臭味相投的朋友来撩.
如您也对开源感兴趣,欢迎加入我们技术团队,诚邀全球各路豪杰,群策群力,打造更好的开源项目.
目前有家淘宝金牌店铺,健身补剂专卖,食品行业营业证照齐全,供应链稳定,但苦于无太多时间经营,未来有计划重振,也招募有志之士一起合作,配有一套本人开源的[健身计划一键生成系统](https://gitee.com/easy-es/fit-plan),可用于给客户提供免费的健身计划.
QQ|微信 (同号) : 252645816
技术&健身讨论群: 247637156
微信群因无群号且动态码,如需进微信群的朋友须先添加本人微信,由本人拉入.
个人技术博客:[CSDN博客](https://blog.csdn.net/lovexiaotaozi)

5
docs/copyright.md Normal file
View File

@ -0,0 +1,5 @@
本框架为了保持与MP一致的语法,有部分代码来源于开源框架[Mybatis-Plus](https://mp.baomidou.com/),或是对其做了修改,在此特别声明.
本框架底层使用了ElasticSearch官方开源框架[RestHighLevelClient](https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/index.html),在此特别声明.
本框架采用和Mybatis-plus一样的[Apache2.0开源协议](https://www.apache.org/licenses/LICENSE-2.0),并且承诺永不参与商业用途,仅供大家无偿使用.

27
docs/create-index.md Normal file
View File

@ -0,0 +1,27 @@
```java
@Test
public void testCreatIndex() {
LambdaEsIndexWrapper<Document> wrapper = new LambdaEsIndexWrapper<>();
// 此处简单起见 索引名称须保持和实体类名称一致,字母小写 后面章节会教大家更如何灵活配置和使用索引
wrapper.indexName(Document.class.getSimpleName().toLowerCase());
// 此处将文章标题映射为keyword类型(不支持分词),文档内容映射为text类型,可缺省
// 支持分词查询,内容分词器可指定,查询分词器也可指定,,均可缺省或只指定其中之一,不指定则为ES默认分词器(standard)
wrapper.mapping(Document::getTitle, FieldType.KEYWORD)
.mapping(Document::getContent, FieldType.TEXT,Analyzer.IK_MAX_WORD,Analyzer.IK_MAX_WORD);
// 设置分片及副本信息,3个shards,2个replicas,可缺省
wrapper.settings(3,2);
// 设置别名信息,可缺省
String aliasName = "daily";
wrapper.createAlias(aliasName);
// 创建索引
boolean isOk = documentMapper.createIndex(wrapper);
Assert.assertTrue(isOk);
}
```
> **Tips:**
> 由于ES索引改动自动重建的特性,因此本接口设计时将创建索引所需的mapping,settings,alias信息三合一了,尽管其中每一项配置都可缺省,但我们仍建议您在创建索引前提前规划好以上信息,可以规避后续修改带来的不必要麻烦,若后续确有修改,您仍可以通过别名迁移的方式(推荐,可平滑过渡),或删除原索引重新创建的方式进行修改.

1
docs/create_index.md Normal file
View File

@ -0,0 +1 @@
create_index.md

12
docs/del-index.md Normal file
View File

@ -0,0 +1,12 @@
> 删除索引,生产环境请谨慎操作,恢复代价和难度高
```java
@Test
public void testDeleteIndex(){
// 测试删除索引
// 指定要删除哪个索引
String indexName = Document.class.getSimpleName().toLowerCase();
boolean isOk = documentMapper.deleteIndex(indexName);
Assert.assertTrue(isOk);
}
```

0
docs/del_index.md Normal file
View File

17
docs/delete.md Normal file
View File

@ -0,0 +1,17 @@
```java
// 根据 ID 删除
Integer deleteById(Serializable id);
// 根据 entity 条件,删除记录
Integer delete(LambdaEsQueryWrapper<T> wrapper);
// 删除根据ID 批量删除)
Integer deleteBatchIds(Collection<? extends Serializable> idList);
```
##### 参数说明
| 类型 | 参数名 | 描述 |
| --- | --- | --- |
| Wrapper<T> | queryWrapper | 实体包装类 QueryWrapper |
| Serializable | id | 主键ID |
| Collection<? extends Serializable> | idList | 主键ID列表 |

0
docs/deleted.md Normal file
View File

144
docs/demo.md Normal file
View File

@ -0,0 +1,144 @@
> 本Demo演示Easy-Es与Springboot项目无缝集成,建议先下载,可直接在您本地运行.
> Demo下载地址: ✔[Gitee](https://gitee.com/easy-es/easy-es-springboot-demo) | ✔ [Github](https://github.com/xpc1024/easy-es-springboot-demo)
# Demo介绍
---
## 1.项目结构
---
![1](https://iknow.hs.net/e562a309-8526-4964-9250-b87ad02545e0.png)
<br />为了演示方便,本demo省略service层
## 2.Pom
---
```xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>ee-use</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>ee-use</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>io.github.xpc1024</groupId>
<artifactId>easy-es-boot-starter</artifactId>
<version>0.9.6</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
```
## 3.核心代码
---
```java
@RestController
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class TestUseEeController {
private final DocumentMapper documentMapper;
@GetMapping("/index")
public Boolean index() {
// 初始化-> 创建索引,相当于MySQL建表 | 此接口须首先调用,只调用一次即可
LambdaEsIndexWrapper<Document> indexWrapper = new LambdaEsIndexWrapper<>();
indexWrapper.indexName(Document.class.getSimpleName().toLowerCase());
indexWrapper.mapping(Document::getTitle, FieldType.KEYWORD)
.mapping(Document::getContent, FieldType.TEXT);
documentMapper.createIndex(indexWrapper);
return Boolean.TRUE;
}
@GetMapping("/insert")
public Integer insert() {
// 初始化-> 新增数据
Document document = new Document();
document.setTitle("老汉");
document.setContent("推*技术过硬");
return documentMapper.insert(document);
}
@GetMapping("/search")
public List<Document> search() {
// 查询出所有标题为老汉的文档列表
LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();
wrapper.eq(Document::getTitle, "老汉");
return documentMapper.selectList(wrapper);
}
}
```
## 4.启动及使用
---
### a.添加配置信息
```yaml
easy-es:
enable: true # 默认为true,若为false时,则认为不启用本框架
address : 127.0.0.0:9200 #填你的es连接地址
# username: 有设置才填写,非必须
# password: 有设置才填写,非必须
```
### b.启动项目
使用你的IDE启动项目<br />
![image.png](https://iknow.hs.net/b6d12f86-58db-45ad-af05-29ab9b398614.png)
### c.使用
依次在浏览器访问<br />[http://localhost:8080/index](http://localhost:8080/index) (仅访问一次即可,完成索引创建,相当于MySQL建表,有了表才能进行后续CRUD)
[http://localhost:8080/insert](http://localhost:8080/insert) (插入数据)
[http://localhost:8080/search](http://localhost:8080/search) (查询)
效果图:<br />
![image.png](https://iknow.hs.net/903287b2-f683-4335-a29a-6b58418b6950.png)<br />
![image.png](https://iknow.hs.net/0c9dd4f1-1b56-4d1a-ba39-cc3bf51d87a3.png)
## 5.结语
---
至此,您已初步体验Easy-Es的基本功能,如果你感觉使用起来体验还不错,想进一步体验更多强大功能,那就继续往下看吧!

68
docs/diff.md Normal file
View File

@ -0,0 +1,68 @@
> 为了减少开发者的额外学习负担,我们尽量保持了和MP几乎一致的语法,但为了避免歧义,仍有个别地方存在些许差异,无论如何,在你看完这些差异和原因后,你肯定也会赞同这种差异存在的必要性.
**1.命名差异**<br />为了区别MP的命名带来的歧义问题,以下三处命名中我们加了Es字母区别于MP:
| | MP | EE | 差异原因 |
| --- | --- | --- | --- |
| 启动类注解 | @MapperScan("xxx") | @EsMapperScan("xxx") | 一个项目中可能会同时用到MP和EE,避免同一系统中同时引入同名注解时,需要加全路径区分 |
| 父类Mapper命名 | BaseMapper<T> | BaseEsMapper<T> | 一个项目中可能会同时用到MP和EE,避免继承时误继承到MP的Mapper |
| 条件构造器命名 | LambdaQueryWrapper | LambdaEsQueryWrapper | 一个项目中可能会同时用到MP和EE,避免错误创建条件构造器 |
**2.移除了Service**<br />MP中引入了Service层,但EE中并无Service层,因为我个人认为MP的Service层太重了,不够灵活,实际开发中基本不用,被很多人吐槽,所以EE中我直接去掉了Service层,在使用过程中你无需像MP那样继承ISevice,另外我把一些高频使用的service层封装的方法下沉到了mapper层,比如批量更新,批量新增等,大家可以在调用基类Mapper层中的方法时看到,灵活且不失优雅.
**3.方法差异**<br />▼ group by 聚合<br />在EE中使用groupBy方法时,调用查询接口必须使用获取原生返回内容,不能像MP中一样返回泛型T,这点是由于ES和MySQL的差导致的,所以需要特别注意
```java
LambdaEsUpdateWrapper<T> wrapper = new LambdaEsUpdateWrapper<>();
wrapper.groupBy(T::getField);
// MP语法
List<T> list = xxxMapper.selectList(wrapper);
// EE语法
SearchResponse response = xxxMapper.search(wrapper);
```
因为Es会把聚合的结果单独放到aggregations对象中,但原来的实体对象中并无此字段,所以我们需要用SearchResponse接收查询返回的结果,我们所需要的所有查询信息都可以从SearchResponse中获取.
```json
"aggregations":{"sterms#creator":{"doc_count_error_upper_bound":0,"sum_other_doc_count":0,"buckets":[{"key":"老汉","doc_count":2},{"key":"老王","doc_count":1}]}}
```
移除了几个低频且不符合编码规范的方法:
```
allEq(Map<R, V> params)
allEq(Map<R, V> params, boolean null2IsNull)
allEq(boolean condition, Map<R, V> params, boolean null2IsNull)
```
你完全可以用eq()方法代替上述方法,可以避免代码中出现魔法值.<br />移除了几个我目前还没看到使用场景的方法:
```
having(String sqlHaving, Object... params)
having(boolean condition, String sqlHaving, Object... params)
func(Consumer<Children> consumer)
func(boolean condition, Consumer<Children> consumer)
```
新增了一些EE有但MP不支持的方法:
```
// 索引创建相关
Boolean existsIndex(String indexName);
Boolean createIndex(LambdaEsIndexWrapper<T> wrapper);
Boolean updateIndex(LambdaEsIndexWrapper<T> wrapper);
Boolean deleteIndex(String indexName);
// 高亮
highLight(高亮字段);
highLight(高亮字段,开始标签,结束标签)
// 权重
function(字段, 值, Float 权重值)
// Geo 地理位置相关
geoBoundingBox(R column, GeoPoint topLeft, GeoPoint bottomRight);
geoDistance(R column, Double distance, DistanceUnit distanceUnit, GeoPoint centralGeoPoint);
geoPolygon(R column, List<GeoPoint> geoPoints)geoShape(R column, String indexedShapeId);
geoShape(R column, String indexedShapeId);
geoShape(R column, Geometry geometry, ShapeRelation shapeRelation);
```
**4.功能阉割**<br />在全局配置,自定义注解上EE支持的功能没有MP那么多,但是已经支持的那些功能用起来与MP一样,目前已经支持了MP中常用的功能,以及高频功能,低频的后续的迭代中也会陆续跟上MP的脚步,尽量做到全支持.
除了需要注意以上列出的这些小差异,其余地方和MP并无差异,使用者完全可以像使用MP一样使用EE

17
docs/donate-log.md Normal file
View File

@ -0,0 +1,17 @@
2021年12月---感谢作者本人为此框架捐赠0.1元,打破了无人捐款的囧境!
2022年1月---感谢CJ捐赠5元,算是真正意义上的首捐,虽然金额不大,但非常感谢这份支持,极大提振了开发者信心
2022年1月---感谢橘子皮先生捐赠6.66元
2022年2月 --- 感谢做好事不留名的 *y 网友捐赠50元请作者喝咖啡
2022年3月--- 感谢chenzf捐赠1元 是码云上的首捐
2022年3月 --- 感谢以梦为马,不负韶华先生捐赠50元
2022年3月 --- 感谢璐先生为本系统官网捐赠服务器
...
感谢以上所有捐赠,感谢大家对开源开发者的肯定和支持,此举也在推动全球开源事业发展,功德无量!

14
docs/donate.md Normal file
View File

@ -0,0 +1,14 @@
> 您的支持是鼓励我们前行的动力,无论金额多少都足够表达您这份心意。
![1](https://iknow.hs.net/bb899d81-0e82-4a96-815f-ab46da5d5822.png)
![2](https://iknow.hs.net/f8164d70-7dbe-4e6a-807a-2fc7405e5bf9.png)
![3](https://iknow.hs.net/7b3c757f-f5fa-43eb-ae64-b11cda4a6fd7.jpg)
捐赠途径: 由于新的政策走向,未来二维码可能无法收款,您亦可通过[Gitee码云平台](https://gitee.com/easy-es/easy-es)本仓库右下角捐赠按钮直接捐赠.
捐赠请备注,我们会将您的捐赠信息上传至本页面,每一份捐赠可根据您的意愿决定是否公示(默认公示).
捐赠形式金额不限,甚至可以捐赠服务器,域名,SSL证书等,每一份捐赠都是对全球开源事业的支持,谢谢您!

0
docs/en/.nojekyll Normal file
View File

View File

@ -0,0 +1,5 @@
> **Instruction:**
> The parent class of QueryWrapper(LambdaEsQueryWrapper) and UpdateWrapper(LambdaEsUpdateWrapper)
> Used to generate the where condition of the statement, and the entity attribute is also used to generate the where condition of the statement
> Note: The where condition generated by the entity has no associated behavior with the where condition generated by each api

1
docs/en/Annotation.md Normal file
View File

@ -0,0 +1 @@

1
docs/en/CNAME Normal file
View File

@ -0,0 +1 @@
easy-es.cn

View File

@ -0,0 +1 @@

View File

@ -0,0 +1 @@

4
docs/en/QueryWrapper.md Normal file
View File

@ -0,0 +1,4 @@
> **Instruction:**
> Inherited from AbstractWrapper, its own internal attribute entity is also used to generate where conditions
> And LambdaEsQueryWrapper

42
docs/en/README.md Normal file
View File

@ -0,0 +1,42 @@
# Introduction
---
Easy-Es (EE for short) is a low-code development framework based on RestHighLevelClient officially provided by ElasticSearch (Es for short). If you have used Mybatis-Plus (MP for short), then you can basically get started with EE at zero learning cost. EE is an Es replacement version of MP, and it also incorporates more unique functions of Es to help you quickly realize various scenarios. development.
> **Philosophy:** Leave simplicity, ease of use, and convenience to users, and leave complexity to the framework.
> **Vision:** Let the world have no difficult Es, and strive to become the world's most popular ElasticSearch search engine development framework.
![1](https://iknow.hs.net/4f7ec0c1-ec40-47a6-9a69-8284cb6563a7.png)
## Advantage
---
- **Block language differences:** Developers only need to know MySQL syntax to use Es.
- **Low code:** Compared with using RestHighLevelClient, the same query can save about 3-5 times the amount of code on average.
- **Easier to get field names:** The field name is obtained directly from the entity, no need to enter the field name string, which improves the readability of the code and eliminates the bugs caused by the omission of the code due to the modification of the field name.
- **Lower the barriers for developers:** Even beginners who only understand the basics of ES can easily control ES.
## Architecture
---
![2](https://iknow.hs.net/e8153631-2f74-427f-82c4-4f009099c62a.jpg)
## Code hosting
---
> [Gitee](https://gitee.com/easy-es/easy-es)✔ 丨 [Github](https://github.com/xpc1024/easy-es)✔
## Participate in contribution
---
We welcome all developers to participate in the improvement of Easy-Es, and we look forward to your contribution.
- **Contribution code:** code address [Easy-ES](https://github.com/xpc1024/easy-es), welcome to submit Issue or Pull Requests
- **Document maintenance:** Document address [Easy-ES](https://www.yuque.com/laohan-14b9d/tald79/qf7ns2), welcome to participate in translation and revision

4
docs/en/UpdateWrapper.md Normal file
View File

@ -0,0 +1,4 @@
> **Instruction:**
> Inherited from AbstractWrapper, its own internal attribute entity is also used to generate where conditions
> And LambdaEsUpdateWrapper

10
docs/en/_coverpage.md Normal file
View File

@ -0,0 +1,10 @@
<!-- _coverpage.md -->
![logo](https://iknow.hs.net/dc1dbd9c-3c6d-463f-98c4-16d186c9ada3.png)
v0.9.6
This framework is provided by [**Gitee**](https://gitee.com/easy-es/easy-es) with high-quality code hosting services
> An easier-to-use ES search engine framework, born to simplify development!
[Example](/en/demo.md)[Getting started](/en/quick-start.md)

6
docs/en/_navbar.md Normal file
View File

@ -0,0 +1,6 @@
<!-- _navbar.md -->
* [Home](/en/)
* [Contact](/en/contact.md)
* Lang
* [English](/en/)
* [中文](/)

75
docs/en/_sidebar.md Normal file
View File

@ -0,0 +1,75 @@
- [Introduction](/en/README.md)
- [Applicable scene](/en/sceen.md)
- [Worry-free](/en/worry-free.md)
- [Quick start](/en/quick-start.md)
- [Springboot integration demo](/en/demo.md)
- Core Function
- [index](/en/index.md)
- [exists index](/en/exists-index.md)
- [delete index](/en/del-index.md)
- [update index](/en/update-index.md)
- [create index](/en/create-index.md)
- [index shard](/en/index-shard.md)
- [index alias](/en/index-alias.md)
- CRUD Interfaces
- [Select](/en/select.md)
- [Update](/en/update.md)
- [Delete](/en/delete.md)
- [Insert](/en/insert.md)
- [Conditional Constructor](/en/condition.md)
- [eq](/en/eq.md)
- [ne](/en/ne.md)
- [match](/en/match.md)
- [gt](/en/gt.md)
- [ge](/en/ge.md)
- [lt](/en/lt.md)
- [le](/en/le.md)
- [between](/en/between.md)
- [notBetween](/en/notBetween.md)
- [like](/en/like.md)
- [notLike](/en/notLike.md)
- [likeLeft](/en/likeLeft.md)
- [likeRight](/en/likeRight.md)
- [isNull](/en/isNull.md)
- [isNotNull](/en/isNotNull.md)
- [in](/en/in.md)
- [notIn](/en/notIn.md)
- [groupBy](/en/groupBy.md)
- [orderByAsc](/en/orderByAsc.md)
- [orderByDesc](/en/orderByDesc.md)
- [or](/en/or.md)
- [and](/en/and.md)
- [limit](/en/limit.md)
- [from](/en/from.md)
- [size](/en/size.md)
- [set](/en/set.md)
- [AbstractWrapper](/en/AbstractWrapper.md)
- [QueryWrapper](/en/QueryWrapper.md)
- [UpdateWrapper](/en/UpdateWrapper.md)
- Expand Fucntion
- [Hybrid query](/en/hybrid-query.md)
- [Es Native query](/en/origin-query.md)
- [source](/en/source.md)
- [pagination](/en/page.md)
- High-level grammar
- [Field Filtering](/en/filter.md)
- [Sort](/en/sort.md)
- [Aggregate query](/en/aggregation.md)
- [Word segmentation query](/en/particple.md)
- [Weight](/en/weight.md)
- [Highlight query](/en/highlight.md)
- [GEO query](/en/geo.md)
- [GeoBoundingBox](/en/geo-bounding-box.md)
- [GeoDistance](/en/geo-distance.md)
- [GeoPolygon](/en/geo-polygon.md)
- [GeoShape](/en/geo-shape.md)
- Annotation
- [Index annotation](/en/index-anno.md)
- [Field annotation](/en/field-anno.md)
- [Primary key annotation](/en/id-anno.md)
- [configuration](/en/config.md)
- [FAQ](/en/faq.md)
- [Difference between EE and MySQL syntax](/en/compare.md)
- [Donate](/en/donate.md)
- [Copyright](/en/copyright.md)

25
docs/en/aggregation.md Normal file
View File

@ -0,0 +1,25 @@
> In MySQL, we can perform group by aggregation by specifying fields, and EE also supports aggregation:
```java
@Test
public void testGroupBy() throws IOException {
LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();
wrapper.like(Document::getContent,"world");
wrapper.groupBy(Document::getCreator);
SearchResponse response = documentMapper.search(wrapper);
System.out.println(response);
}
```
> **Tips:**
> The aggregation result of Es is placed in a separate object, so we need to use a semi-native query method to return SearchResponse to get the aggregation result
Other aggregations:
```java
// Find the minimum
wrapper.min();
// Find the maximum
wrapper.max();
// average
wrapper.avg();
wrapper.sum();
```

5
docs/en/and.md Normal file
View File

@ -0,0 +1,5 @@
```java
and(Consumer<Param> consumer)
and(boolean condition, Consumer<Param> consumer)
```
● AND nesting<br />● Example: and(i -> i.eq(Document::getTitle, "Hello").ne(Document::getCreator, "Guy"))--->and (title ='Hello' and creator != 'Guy' )

5
docs/en/between.md Normal file
View File

@ -0,0 +1,5 @@
```java
between(R column, Object val1, Object val2)
between(boolean condition, R column, Object val1, Object val2)
```
● BETWEEN value 1 AND value 2<br />● Example: between("age", 18, 30)--->age between 18 and 30

35
docs/en/compare.md Normal file
View File

@ -0,0 +1,35 @@
| MySQL | Easy-Es |
| --- | --- |
| and | and |
| or | or |
| = | eq |
| != | ne |
| > | gt |
| >= | ge |
| < | lt |
| <= | le |
| like '%field%' | like |
| not like '%field%' | notLike |
| like '%field' | likeLeft |
| like 'field%' | likeRight |
| between | between |
| notBetween | notBetween |
| is null | isNull |
| is notNull | isNotNull |
| in | in |
| not in | notIn |
| group by | groupBy |
| order by | orderBy |
| min | min |
| max | max |
| avg | avg |
| sum | sum |
| sum | sum |
| - | orderByAsc |
| - | orderByDesc |
| - | match |
| - | highLight |
| ... | ... |

17
docs/en/condition.md Normal file
View File

@ -0,0 +1,17 @@
> **Instruction:**
> - The first input parameter boolean condition that appears below indicates whether the condition is added to the last generated statement, for example: query.like(StringUtils.isNotBlank(name), Entity::getName, name) .eq(age!=null && age >= 0, Entity::getAge, age)
> - The multiple methods in the following code block are all input parameters of individual boolean types from top to bottom, and the default is true
> - The generic Param appearing below are all subclass instances of Wrapper (all have all the methods of AbstractWrapper)
> - The R that appears in the input parameters of the following methods is generic, String in ordinary wrapper, and function in LambdaWrapper (example: Entity::getId, Entity is the entity class, getId is the getMethod of the field id)
> - The R column in the input parameters of the following methods all represent database fields. When the specific type of R is String, it is the database field name (the field name is the database keyword and it is wrapped by an escape character!)! Not the entity data field name! !!, when the specific type of R is SFunction, the project runtime does not support eclipse's own compiler!!!
> - The following examples are all using ordinary wrappers, and the input parameters are Map and List in the form of json!
> - If the input Map or List is empty during use, it will not be added to the final generated SQL!
> **Warn:**
> - Does not support and does not support the transmission of Wrapper in RPC calls
>
wrapper is heavy
> - The transmission wrapper can be analogous to your controller using a map to receive the value (the development is cool, and the crematorium is maintained)
> - The correct RPC call posture is to write a DTO for transmission, and the callee then performs corresponding operations based on the DTO
> - We refuse to accept any issues or even pr related to RPC transmission Wrapper errors

46
docs/en/config.md Normal file
View File

@ -0,0 +1,46 @@
> **Basic configuration:**
> If it is missing, it can cause the project to fail to start normally
```yaml
easy-es:
eanble: true # The default value is true, If the value of enable is false, it is considered that Easy-es is not enabled
address: 127.0.0.0:9200 # Your elasticsearch address,must contains port, If it is a cluster, please separate with',' just like this: 127.0.0.0:9200,127.0.0.1:9200
username: elastic # Es username, Not necessary, If it is not set in your elasticsearch, delete this line
password: WG7WVmuNMtM4GwNYkyWH # Es password, Not necessary, If it is not set, delete this line
```
> **Extended configuration:**
> It can be defaulted, in order to improve production performance, you can configure it further (only supported in version 0.9.4+)
```yaml
easy-es:
connectTimeout: 5000 # Connection timeout unit: ms
socketTimeout: 5000 # Communication timeout unit: ms
requestTimeout: 5000 # Request timeout unit: ms
connectionRequestTimeout: 5000 # Connection request timeout
maxConnTotal: 100 # Maximum number of connections
maxConnPerRoute: 100 # Maximum number of connected routes
```
> **Global configuration:**
> Can be defaulted, does not affect the project startup, if the default is the default value
```yaml
easy-es:
global-config:
db-config:
table-prefix: dev_ # Index prefix, can be used to distinguish the environment, the default is empty
id-type: auto # id generation strategy defaults to auto
field-strategy: not_empty # The field update strategy defaults to not_null, and the field is updated only when the field value is not empty
```
> **Tips:**
> - id-type supports 2 types:
>
auto: It is automatically generated by ES and is the default configuration, no additional configuration is required for you. Recommended
> uuid: The system generates UUID, and then inserts ES (not recommended)
> - Field-strategy supports 3 types:
> - not_null: non-Null judgment, only when the field value is non-Null will be updated
> - not_empty: non-empty judgment, will be updated only when the field value is a non-empty string
> - ignore: Ignore the judgment, no matter what the field value is, it will be updated
> - After configuring the global policy, you can still customize the configuration for individual classes through annotations, and the priority of the global configuration is lower than the annotation configuration

14
docs/en/contact.md Normal file
View File

@ -0,0 +1,14 @@
Base: Hangzhou
developed as full-stack for 5 years, and has been a muscular man for 8 years. Welcome friends with similar smells to tease.
If you are also interested in open source, welcome to join our technical team, we sincerely invite heroes from all over the world to work together to create better open source projects.
At present, there is a Taobao store, which specializes in fitness supplements. The food industry has complete business licenses and a stable supply chain. However, due to the lack of time to operate, there are plans to revive in the future. [One-click fitness plan generation system](https://gitee.com/easy-es/fit-plan), which can be used to provide customers with free fitness plans.
QQ|WeChat (same number) : 252645816
Technology & Fitness Discussion Group: 247637156
Because there is no group number and dynamic code in the WeChat group, if you want to join the WeChat group, you must add your own WeChat first, and then pull it in by yourself.

5
docs/en/copyright.md Normal file
View File

@ -0,0 +1,5 @@
In order to maintain the syntax of this framework consistent with MP, some of the code comes from the open source framework [Mybatis-Plus](https://mp.baomidou.com/), or has been modified, which is specially stated here.
The bottom layer of this framework uses ElasticSearch's official open source framework [RestHighLevelClient](https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/index.html), which is specifically stated here.
This framework adopts the same [Apache2.0 License](https://www.apache.org/licenses/LICENSE-2.0) as Mybatis-plus, and promises to never participate in commercial use, and is only for free use by everyone.

27
docs/en/create-index.md Normal file
View File

@ -0,0 +1,27 @@
```java
@Test
public void testCreatIndex() {
LambdaEsIndexWrapper<Document> wrapper = new LambdaEsIndexWrapper<>();
// For the sake of simplicity here, the index name must be consistent with the entity class name, with lowercase letters. Later chapters will teach you how to configure and use the index more flexibly
wrapper.indexName(Document.class.getSimpleName().toLowerCase());
// Here, the article title is mapped to the keyword type (word segmentation is not supported), and the document content is mapped to the text type (word segmentation query is supported), which can be defaulted
wrapper.mapping(Document::getTitle, FieldType.KEYWORD)
.mapping(Document::getContent, FieldType.TEXT);
// Set shard and replica information, here 3 shards and 2 replicas are set, which can be defaulted
wrapper.settings(3,2);
// Set alias information, which can be defaulted
String aliasName = "dev";
wrapper.createAlias(aliasName);
// execute create index
boolean isOk = documentMapper.createIndex(wrapper);
Assert.assertTrue(isOk);
}
```
> **Tips:**
> Due to the feature of automatic reconstruction of ES index changes, the mapping, settings, and alias information required to create the index are three-in-one during the design of this interface. Although each configuration can be defaulted, we still recommend that you create the index plan the above information in advance to avoid unnecessary trouble caused by subsequent modifications. If there are subsequent modifications, you can still modify it by alias migration (recommended, smooth transition), or delete the original index and recreate it. .
>

10
docs/en/del-index.md Normal file
View File

@ -0,0 +1,10 @@
> Delete the index, please operate with caution in the production environment, the recovery cost and difficulty are high
```java
@Test
public void testDeleteIndex(){
String indexName = Document.class.getSimpleName().toLowerCase();
boolean isOk = documentMapper.deleteIndex(indexName);
Assert.assertTrue(isOk);
}
```

16
docs/en/delete.md Normal file
View File

@ -0,0 +1,16 @@
```java
Integer deleteById(Serializable id);
// delete based on conditions
Integer delete(LambdaEsQueryWrapper<T> wrapper);
Integer deleteBatchIds(Collection<? extends Serializable> idList);
```
**Parameter Description**
| Type | Parameter name | Description |
| --- | --- | --- |
| Wrapper<T> | wrapper | Delete conditional packaging |
| Serializable | id | primary key in es |
| Collection<? extends Serializable> | idList | primary key list in es |

47
docs/en/demo.md Normal file
View File

@ -0,0 +1,47 @@
> This Demo demonstrates the use of Easy-Es in the Springboot project. It is recommended to download it first and run it directly on your local.
> Demo download link: [Github](https://github.com/xpc1024/easy-es-springboot-demo-en)
# Demo introduction
---
## 1. Project structure
---
![](https://cdn.nlark.com/yuque/0/2021/png/21559896/1638952452520-10d0b15d-4a46-4d0e-9c6d-b3a4f859e587.png#crop=0&crop=0&crop=1&crop=1&from=url&id=XbyNe&margin=%5Bobject%20Object%5D&originHeight=299&originWidth=400&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=)
## 2.Configuration
---
```yaml
easy-es:
eanble: true # The default value is true, If the value of enable is false, it is considered that Easy-es is not enabled
address: 127.0.0.0:9200 # Your elasticsearch address,must contains port, If it is a cluster, please separate with',' just like this: 127.0.0.0:9200,127.0.0.1:9200
username: elastic # Es username, Not necessary, If it is not set in your elasticsearch, delete this line
password: WG7WVmuNMtM4GwNYkyWH # Es password, Not necessary, If it is not set, delete this line
```
## 3.Run
---
Use your IDE to start the project:<br />![](https://cdn.nlark.com/yuque/0/2021/png/21559896/1638952870873-8d460b56-327f-4fa7-99cd-a65e64ce0716.png#crop=0&crop=0&crop=1&crop=1&from=url&id=qLoIq&margin=%5Bobject%20Object%5D&originHeight=42&originWidth=335&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=)
## 4.Use
---
Use your browser or postman to request the following addresses in turn:
- [http://localhost:8080/index](http://localhost:8080/index) (create index, must be requested first and only once)
- [http://localhost:8080/insert](http://localhost:8080/insert) (create data)
- [http://localhost:8080/search](http://localhost:8080/search) (search data)
> Then you will get the result what you searched in your browser or postman.
## 5.Summary
---
At this point, you have initially experienced the basic functions of Easy-Es. If you feel that the experience is good, and you want to further experience more powerful functions, you can check the reference document.

21
docs/en/donate.md Normal file
View File

@ -0,0 +1,21 @@
> Your support is the motivation to encourage us to move forward, no matter how much money is, it is enough to express your wishes.
author's wechat account or alipay:
![1](https://iknow.hs.net/f8164d70-7dbe-4e6a-807a-2fc7405e5bf9.png)
![2](https://iknow.hs.net/7b3c757f-f5fa-43eb-ae64-b11cda4a6fd7.jpg)
Visa Debit:
6217930275445975 cardholder:pengcheng xing Bank:Shanghai Pudong Development Bank
> - Please note for donations, we will upload your donation information to this page, and each donation can be publicized according to your wishes.
> - There is no limit to the amount of donation, and there is currently no server. If you can donate a server or domain name, in return, we will place advertisements and donate information for you in the designated area of the page for free.
Author's e-mail:252645816@qq.com

5
docs/en/eq.md Normal file
View File

@ -0,0 +1,5 @@
```java
eq(R column, Object val)
eq(boolean condition, R column, Object val)
```
● equal to =<br />● Example: eq("name", "Jimmy")-->name ='Jimmy'

10
docs/en/exists-index.md Normal file
View File

@ -0,0 +1,10 @@
> Can be used to verify whether there is an index with the specified name
```java
@Test
public void testExistsIndex(){
String indexName = Document.class.getSimpleName().toLowerCase();
boolean existsIndex = documentMapper.existsIndex(indexName);
Assert.assertTrue(existsIndex);
}
```

38
docs/en/faq.md Normal file
View File

@ -0,0 +1,38 @@
> Since EE has not been used by a large number of users, there is no FAQ for the time being, and it will continue to be updated in the future. Here are some common questions I encountered that may be asked
1. During the trial process, an error was reported: java.lang.reflect.UndeclaredThrowableException
```
Caused by: [daily_document] ElasticsearchStatusException[Elasticsearch exception [type=index_not_found_exception, reason=no such index [daily_document]]]
```
If your error message and cause are consistent with the above, please check whether the index name is correctly configured, check the global configuration, and annotate the configuration. If the configuration is correct, it may be that the index does not exist. You can check whether the specified index already exists through the es-head visualization tool If there is no such index, it can be quickly created through the API provided by EE.
2. Dependence conflict
Although the EE framework is light enough and I try to avoid using too many other dependencies during the development process, it is still difficult to guarantee that dependency conflicts with the host project will occur with a very small probability. If there is a dependency conflict, the developer can use the migration Except for repetitive dependencies or unified version numbers to resolve, all EE dependencies that may conflict are as follows:
```xml
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.10.1</version>
</dependency>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>7.10.1</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.79</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.6</version>
</dependency>
```

26
docs/en/field-anno.md Normal file
View File

@ -0,0 +1,26 @@
> The field annotation @TableField function is the same as [Mybatis-Plus](https://github.com/baomidou/mybatis-plus)(Hereafter referred to as MP), but compared to MP, some low-frequency use functions have been castrated. Follow-up based on user feedback can be gradually added with the iteration. The current version currently only supports the following two scenarios:
>
> 1. The field in the entity class is not the actual field in ES. For example, the entity class is directly used as DTO, and some extraneous fields that do not exist in ES are added. At this time, this field can be marked so that the EE framework can skip this Field, this field is not processed.
> 1. The update strategy of the field, for example, when the update interface is called, the field of the entity class is not updated until it is not Null or a non-empty string. At this time, you can add field annotations and mark the update strategy for the specified field.
Example of use:
```java
public class Document {
// Other fields are omitted here...
// Scenario 1: mark fields that do not exist in es
@TableField(exist = false)
private String notExistsField;
// Scenario 2: When updating, the non-empty string in this field will be updated
@TableField(strategy = FieldStrategy.NOT_EMPTY)
private String creator;
}
```
> **Tips:**
> - There are 3 types of update strategies:
> - NOT_NULL: Non-Null judgment, only when the field value is non-Null, it will be updated
> - NOT_EMPTY: non-empty judgment, will be updated only when the field value is a non-empty string
> - IGNORE: Ignore the judgment, no matter what the field value is, it will be updated
> - Priority: The update strategy specified in the field annotations> the update strategy specified in the global configuration

38
docs/en/filter.md Normal file
View File

@ -0,0 +1,38 @@
> If you dont want to check some large fields in some queries, you can filter the query fields
## 1.Forward filtering (only query specified fields)
```java
@Test
public void testFilterField() {
LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();
String title = "Hello";
wrapper.eq(Document::getTitle, title);
// only query title field
wrapper.select(Document::getTitle);
Document document = documentMapper.selectOne(wrapper);
System.out.println(document);
}
```
## 2.Reverse filtering (do not query the specified field)
```java
@Test
public void testNotFilterField() {
// Do not query the specified field (recommended)
LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();
String title = "Hello";
wrapper.eq(Document::getTitle, title);
// don't select title field
wrapper.notSelect(Document::getTitle);
Document document = documentMapper.selectOne(wrapper);
System.out.println(document);
// Another way to achieve
LambdaEsQueryWrapper<Document> wrapper1 = new LambdaEsQueryWrapper<>();
wrapper1.select(Document.class, d -> !Objects.equals(d.getColumn(), "title"));
Document document1 = documentMapper.selectOne(wrapper);
System.out.println(document1);
}
```
> **Tips:**
> You can only choose one of forward filtering and reverse filtering. If you use both filtering rules at the same time, the conflicting field will lose the filtering effect.

4
docs/en/from.md Normal file
View File

@ -0,0 +1,4 @@
```java
from(Integer from)
```
● Start the query from the first data, which is equivalent to m in limit (m,n) in MySQL.<br />● Example: from(10)--->Start query from the 10th data

5
docs/en/ge.md Normal file
View File

@ -0,0 +1,5 @@
```java
ge(R column, Object val)
ge(boolean condition, R column, Object val)
```
● Greater than or equal to >=<br />● Example: ge("age", 18)--->age >= 18

View File

@ -0,0 +1,42 @@
GeoBoundingBox: Literally translated as a geographic bounding box, a rectangular range formed by the upper left point and the lower right point, all points within this range can be queried, but not many are actually used, please refer to the following figure:
![1](https://iknow.hs.net/c3703152-b379-4394-8c24-ccfd08f5981b.png)
API:
```java
geoBoundingBox(R column, GeoPoint topLeft, GeoPoint bottomRight)
```
Example of use:
```java
@Test
public void testGeoBoundingBox() {
// Query all points within the rectangle formed by the coordinates of the upper left and lower right points
LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();
GeoPoint leftTop = new GeoPoint(41.187328D, 115.498353D);
GeoPoint bottomRight = new GeoPoint(39.084509D, 117.610461D);
wrapper.geoBoundingBox(Document::getLocation, leftTop, bottomRight);
List<Document> documents = documentMapper.selectList(wrapper);
documents.forEach(System.out::println);
}
```
> **Tips:**
> 1. The above example only demonstrates one of them. In fact, there are many syntax support for coordinate points in this framework. Several data formats officially provided by ElasticSearch are supported. Users can choose the corresponding api according to their own habits to construct query parameters:
> - **GeoPoint:** The latitude and longitude representation used in the demo above
> - **Longitude and latitude array:**[116.498353, 40.187328],[116.610461, 40.084509]
> - **Latitude and longitude strings:** "40.187328, 116.498353", "116.610461, 40.084509
> - **Latitude and longitude bounding box WKT: **"BBOX (116.498353,116.610461,40.187328,40.084509)"
> - **Latitude and longitude GeoHash (hash):** "xxx"
>
Among them, the conversion of latitude and longitude hash can refer to this website: [GeoHash Coordinate Online Conversion](http://geohash.co/)
>
> 2. The index type of the field must be geoPoint, otherwise the related query API will fail, please refer to the following figure.
> 2. The field type is recommended to use String, because the wkt text format is String, which is very convenient. As for the field name, you can see the name.
![](https://iknow.hs.net/90dde93d-653d-4973-9d6f-4068d625f396.png)
```java
public class Document {
// Omit other fields ...
private String location;
}
```

27
docs/en/geo-distance.md Normal file
View File

@ -0,0 +1,27 @@
GeoDistance: Literally translated as geographic distance, in fact, it takes a given point as the center, draws a circle with a given radius, and the points within this circle can be detected and used more frequently, such as the takeaway we use Software, you can use this function to query all the stores within 3 kilometers around, yes, you can also use it to write social software to query the beautiful women within 3 kilometers nearby...
![1](https://iknow.hs.net/b979de3a-3130-4c42-be01-8cf74435e9c8.png)
```java
geoDistance(R column, Double distance, DistanceUnit distanceUnit, GeoPoint centralGeoPoint)
```
```java
@Test
public void testGeoDistance() {
// Query all points within a radius of 168.8 kilometers with a longitude of 41.0 and a latitude of 115.0 as the center and a radius of 168.8 kilometers.
LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();
// The unit can be omitted, the default is km
wrapper.geoDistance(Document::getLocation, 168.8, DistanceUnit.KILOMETERS, new GeoPoint(41.0, 116.0));
// The above syntax can also be written in the following forms, the effect is the same, and it is compatible with different user habits:
// wrapper.geoDistance(Document::getLocation,"1.5km",new GeoPoint(41.0,115.0));
// wrapper.geoDistance(Document::getLocation, "1.5km", "41.0,115.0");
List<Document> documents = documentMapper.selectList(wrapper);
System.out.println(documents);
}
```
> Tips:
> 1. The same form of expression for coordinate points is also supported, which is the same as the Tips in GeoBondingBox, and will not be repeated here.
> 1. The index type and field type are the same as those described in the Tips in GeoBondingBox
> 1. For fans of EE, it is a matter of course to be compatible with the different habits of various users, so you will find a lot of method overloading when you use it. Choose an API that best suits your usage habits or the specified usage scenario to call. .

30
docs/en/geo-polygon.md Normal file
View File

@ -0,0 +1,30 @@
GeoPolygon: Literally translated as geographic polygon, in fact, it takes the polygon formed by all the given points as the range, and queries all the points within this range. This function is often used for electronic fences, and it is used more frequently, such as sharing bicycles. The parking area can be realized by this technology, please refer to the following figure:
![1](https://iknow.hs.net/b979de3a-3130-4c42-be01-8cf74435e9c8.png)
API:
```java
geoPolygon(R column, List<GeoPoint> geoPoints)
```
Example of use:
```java
@Test
public void testGeoPolygon() {
// Query all points in an irregular graph composed of a given list of points, the number of points is at least 3
LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();
List<GeoPoint> geoPoints = new ArrayList<>();
GeoPoint geoPoint = new GeoPoint(40.178012, 116.577188);
GeoPoint geoPoint1 = new GeoPoint(40.169329, 116.586315);
GeoPoint geoPoint2 = new GeoPoint(40.178288, 116.591813);
geoPoints.add(geoPoint);
geoPoints.add(geoPoint1);
geoPoints.add(geoPoint2);
wrapper.geoPolygon(Document::getLocation, geoPoints);
List<Document> documents = documentMapper.selectList(wrapper);
System.out.println(documents);
}
```
> **Tips:**
> 1. Similarly, regarding the input parameter form of the coordinate point, it also supports a variety of forms. It is consistent with the official. You can refer to the Tips in GeoBoundingBox, which will not be repeated here. It is worth noting that the number of points in the polygon cannot be less than 3, otherwise Es cannot outline the polygon. , this query will report an error.
> 1. The index type and field type are the same as those described in the Tips in GeoBondingBox

65
docs/en/geo-shape.md Normal file
View File

@ -0,0 +1,65 @@
GeoShape: Literally translated as geographic graphics, how do you understand it? At first glance, it seems to be very similar to GeoPolygon, but in fact, the first three types of queries are all coordinate points, and this method queries graphics, such as a park, from the world map. It can be regarded as a point, but if the map is made large enough, for example, the map is specific to Binjiang District, Hangzhou, the park may become an area composed of several points. In some special scenarios, you need to query this complete Area, and the intersection of two areas, etc., you need to use GeoShape. If you dont understand it, you might as well read it down first. Take Hangzhou as an example. I will give an example of a health code, assuming the area inside the black circle. For the medium-risk area, I now want to find out all the people in the ES who are in the civic center and in the medium-risk area, and turn all their health codes into orange. In fact, what I am looking for is the orange area in the picture below. At this time, the area formed by the red arrow is the entire civic center. I can use the entire civic center as a geographic graph, and then use the large black circle as the query graph to find their intersection.
![1](https://iknow.hs.net/9f1e6b34-073e-428c-8c7f-86a6bc82d243.png)
The ShapeRelation corresponding to the above figure is INTERSECTS, take a look at the following API.
API:
```java
geoShape(R column, String indexedShapeId);
geoShape(R column, Geometry geometry, ShapeRelation shapeRelation);
```
Example of use:<br />This API is not commonly used, you can also skip directly to see the query by graph below.
```java
/**
* Known graphics index ID (not commonly used)
* In some high-frequency scenarios, such as a park that has already been built, the graphics coordinates are fixed, so this fixed graphics can be stored in es first
* Follow-up can be directly queried based on the id of this graph, which is more convenient, so there is this method, but it is not flexible enough and not commonly used
*/
@Test
public void testGeoShapeWithShapeId() {
LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();
// The indexedShapeId here is the id of the shape that the user has created in Es in advance
wrapper.geoShape(Document::getGeoLocation, "edu");
List<Document> documents = documentMapper.selectList(wrapper);
System.out.println(documents);
}
```
This API is more commonly used than the above method, that is, the user can specify whether the graph to be queried is a rectangle, a circle, or a polygon... (see the comments in the code for details):
```java
/**
* Graphics are customized by users (commonly used), this framework supports all supported graphics of Es:
* (Point,MultiPoint,Line,MultiLine,Circle,LineaRing,Polygon,MultiPolygon,Rectangle)
*/
@Test
public void testGeoShape() {
// Note that the graph is queried here, so the field index type of the graph must be geoShape, not geoPoint, so the geoLocation field is used instead of the location field
LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();
Circle circle = new Circle(13,14,100);
// shapeRelation supports multiple types, if not passed, it defaults to within
wrapper.geoShape(Document::getGeoLocation, circle, ShapeRelation.INTERSECTS);
List<Document> documents = documentMapper.selectList(wrapper);
System.out.println(documents);
}
```
in the above map
WKT (Well-Known Text) coordinates of the civic center (polygon) (simulated data, real data can be obtained from AutoNavi Map/Baidu Map, etc. by calling the open API provided by them): "POLYGON((108.36549282073975 22.797566864832092,108.35974216461182 22.786093175673713)
It has been stored in Es. In fact, we will store all the data or business data that may be used in the project in Es in advance. Otherwise, the query will be meaningless. Check the air?
So when the above API queries based on GeoShape, the parameter that needs to be passed in is only the graph of the range you delineate (the parameter above is a circle).
> **TIps:**
> - GeoShape is easy to be confused with GeoPolygon and needs special attention, they are actually two different things.
> - The field index type for GeoShape query must be geo_shape type, otherwise this API cannot be used, refer to the following figure
> - The field type is recommended to use String, because the wkt text format is String, which is very convenient. As for the field name, you can see the name.
![2](https://iknow.hs.net/17915c0a-151e-497b-bd0f-5f70868d35a6.png)
```java
public class Document {
// Omit other fields ...
private String geoLocation;
}
```

40
docs/en/geo.md Normal file
View File

@ -0,0 +1,40 @@
> Supported Versions: 0.9.5+
> Geographical location query, which is exactly the same as the function provided by Es official, supports a total of 4 types of geographic location query:
> - GeoBoundingBox
> - GeoDistance
> - GeoPolygon
> - GeoShape
>
Through these four types of queries, various powerful and practical functions can be realized
Application Scenario:
● Stores near takeaway apps
● People near social apps
● Drivers near taxi apps
● Crowd feature extraction within the specified range of regional crowd portrait APPs
● Health code, etc.
● ...
The function coverage is 100%, and the use is simpler. For the detailed introduction of the 4 types of queries, please click the left menu to enter the sub-items to view
> **Tips:**
> 1. Before using the geolocation query API, you need to create or update the index in advance
> - The first three types of API (GeoBoundingBox, GeoDistance, GeoPolygon) field index type must be geo_point
> - GeoShape field index type must be geo_shape, please refer to the following figure for details
>
> 2.The field type is recommended to use String, because the wkt text format is String, which is very convenient. As for the field name, you can see the name.
![](https://iknow.hs.net/94fcefcc-3bfd-48c6-99fa-2bfa6d803f20.png)
```java
public class Document {
// Omit other fields...
private String location;
private String geoLocation;
}
```

5
docs/en/groupBy.md Normal file
View File

@ -0,0 +1,5 @@
```java
groupBy(R... columns)
groupBy(boolean condition, R... columns)
```
● Grouping: GROUP BY field, ...<br />● Example: groupBy(Document::getId,Document::getTitle)--->group by id,title

5
docs/en/gt.md Normal file
View File

@ -0,0 +1,5 @@
```java
gt(R column, Object val)
gt(boolean condition, R column, Object val)
```
● Greater than><br />● Example: gt("age", 18)--->age> 18

22
docs/en/highlight.md Normal file
View File

@ -0,0 +1,22 @@
**syntax:**
```java
// Do not specify the highlight tag, and use <em>your highlight content</em> to return the highlighted content by default
highLight(highlightField);
// Specify highlight label
highLight(highlightField,startTag, endTag)
```
```java
@Test
public void testHighlight() throws IOException {
LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();
String keyword = "World";
wrapper.match(Document::getContent,keyword);
wrapper.highLight(Document::getContent);
SearchResponse response = documentMapper.search(wrapper);
System.out.println(response);
}
```
> **Tips:**
> If you need to highlight multiple fields, you can separate the fields with commas
> Must use SearchResponse to receive, otherwise there is no highlighted field in the return body

47
docs/en/hybrid-query.md Normal file
View File

@ -0,0 +1,47 @@
# What is a mixed query?
A simple understanding is that half of it adopts the syntax of EE, and half of it adopts the syntax of RestHighLevelClient, which is similar to "Hybrid". I believe you will fall in love with this "Hybrid" mode, because it combines the advantages of both modes!
# Why have hybrid queries?
Because EE has not yet achieved 100% coverage of the functions of RestHighLevelClient, at the initial stage of open source, it only covers about 90% of the functions of RestHighLevelClient, and 99% of the core high-frequency use functions, so it is inevitable that there will be individual scenarios. EE cannot meet a certain special requirement. At this time, the secondary development of the EE framework or the requirement is directly submitted to the EE author, which cannot meet the developer's needs in terms of time. Some requirements may be tighter than the product manager. , you can solve the dilemma by mixing queries.
# How to use hybrid query?
When I did not provide this document, although I provided an API and a brief introduction to the mixed query, many people still do not know this function, let alone how to use it, so here I will use a specific case to demonstrate to you How to use mixed query is for your reference, please don't worry about the space, it's actually very, very simple, just the details of my tutorial.
> **Background:** User "Xiangyang" WeChat feedback to me that currently EE does not support query sorting from near to far from a given point.
> In actual development, this scenario can be applied to "the passenger places an order and asks to give priority to the driver closest to me within 3 kilometers" when taking a taxi, and then the passenger is a beautiful woman, worried about her own safety, and added a few more requirements. , For example, the driver must be a female, the driving experience is more than 3 years, and the commercial vehicle, etc...
Taking the taxi-hailing scenario above as an example, let's see how to use EE to query? The above query can be divided into two parts
● Routine queries supported by EE: If the driver is female within 3 kilometers of the surrounding area, and the driving age is >= 3 years...
● Unconventional queries not supported by EE: sorting according to complex sorting rules (currently EE only supports ascending/descending sorting of regular fields)
For the supported part, we can directly call EE, and EE builds a SearchSourceBuilder first.
```java
// Suppose the latitude and longitude of the passenger's location is 31.256224D, 121.462311D
LambdaEsQueryWrapper<Driver> wrapper = new LambdaEsQueryWrapper<>();
wrapper.geoDistance(Driver::getLocation, 3.0, DistanceUnit.KILOMETERS, new GeoPoint(31.256224D, 121.462311D));
.eq(Driver::getGender,"Female")
.ge(Driver::getDriverAge,3)
.eq(Driver::getCarModel,"business car");
SearchSourceBuilder searchSourceBuilder = driverMapper.getSearchSourceBuilder(wrapper);
```
For unsupported statements, you can continue to encapsulate them with the syntax of RestHighLevelClient. After encapsulation, you can directly call the native query interface provided by EE to complete the entire query.
```java
SearchRequest searchRequest = new SearchRequest("indexName");
// The searchSourceBuilder here is constructed from the above EE, and we continue to append sorting parameters to it
searchSourceBuilder.sort(
new GeoDistanceSortBuilder("location", 31.256224D, 121.462311D)
.order(SortOrder.DESC)
.unit(DistanceUnit.KILOMETERS)
.geoDistance(GeoDistance.ARC)
);
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = driverMapper.search(searchRequest, RequestOptions.DEFAULT);
```
In this way, you can not only enjoy the basic queries generated by EE for you, but also complete the functions that EE does not currently support. You only need a lot of code (compared to the direct RestHighLevelClient, it can still save a lot of code) to achieve your The goal is similar to a compromise solution under the condition that pure electric vehicles have not yet fully developed, namely gasoline-electric hybrid.
Of course, if you are not used to using this mode, you can still use the native query directly, so you can use EE without any worries. We have already figured out various solutions and fallbacks for you, and after-sales is worry-free! If you also agree with this model, you may wish to give the author a thumbs up. In order to make EE users happy, the author's bad old man can be described as painstaking!
# Epilogue
Because the functions supported by RestHighLevel officially provided by ES are really too numerous, although I am still integrating various new functions non-stop, and repairing user feedback problems, optimizing the performance of existing code, but there will inevitably be some The function can not meet your current needs, please forgive me, my lords, EE has only been born for three months, it is impossible to be perfect, please give us a little time, these so-called shortcomings will be solved, just like new energy vehicles will eventually be in the future. Gradually replace the fuel car, those so-called problems will not be a problem in the future, Ullah!

25
docs/en/id-anno.md Normal file
View File

@ -0,0 +1,25 @@
> The primary key annotation @TableId function is the same as[ Mybatis-Plus](https://github.com/baomidou/mybatis-plus)(Hereafter referred to as MP), but compared to MP, some low-frequency usage functions have been castrated. According to user feedback, it can be added gradually with the iteration. The current version currently only supports the following two scenarios:
>
> 1. Rename the unique id in es
> 1. Specify the unique id generation method in es
Example:
```java
public class Document {
/**
* unique id in es
*/
@TableId(value = "myId",type = IdType.AUTO)
private String id;
// Omit other fields...
}
```
> **Tips:**
> - Since es has processed the default name of id (underscore + id): _id, EE has blocked this operation for you, you don't need to specify it in the annotation, and the framework will automatically complete the mapping for you.
> - Id generation types currently only support three types:
> 1. **IdType.AUTO:** It is automatically generated by ES and is the default configuration, no additional configuration is required for you. Recommended
> 1. **IdType.UUID:** The system generates UUID, and then inserts ES (not recommended)
> 1. **IdType.CUSTOMIZE:** (version number >= 0.9.6 support) is defined by the user, the user sets the id value by himself, if the id specified by the user does not exist in es, a new record will be added when inserting, if If the user-specified id already has a record in es, the record corresponding to the id will be updated automatically.
> - **Priority:** Annotation configured Id generation strategy>Globally configured Id generation strategy

11
docs/en/in.md Normal file
View File

@ -0,0 +1,11 @@
```java
in(R column, Collection<?> value)
in(boolean condition, R column, Collection<?> value)
```
● Field in (value.get(0), value.get(1), ...)<br />● Example: in("age",{1,2,3})--->age in (1,2,3)
```java
in(R column, Object... values)
in(boolean condition, R column, Object... values)
```
● Field in (v0, v1, ...)<br />● Example: in("age", 1, 2, 3)--->age in (1,2,3)

7
docs/en/index-alias.md Normal file
View File

@ -0,0 +1,7 @@
```java
/**
* Set alias information
* @param aliasName
*/
createAlias(String aliasName)
```

17
docs/en/index-anno.md Normal file
View File

@ -0,0 +1,17 @@
> - Index If the user does not configure or specify an annotation, the lowercase letters of the model name will be used as the index. For example, if the model is called Document, then the index will be document.
> - We also support specifying the index name according to the @TableName annotation.In order to maintain the same syntax as MP, the annotation naming here will temporarily retain @TableName, but it actually represents the index name.
Usage example: Assuming that my index name is: dev_document, then we can add this annotation to the model
```java
@TableName("dev_document")
public class Document {
...
}
```
> Tips:
> - The index name specified by the annotation has the highest priority. If the annotation index is specified, the global configuration and automatically generated index will not take effect, and the index name specified in the annotation will be used. Priority order: Annotation index>Global configuration index prefix>Auto generated
> - The keepGlobalPrefix option, (only supported in version 0.9.4+), the default value is false, whether to keep using the global tablePrefix value:
> - This annotation option will only take effect when the global tablePrefix is configured, the @TableName annotation and the value value are specified. If its value is true, the index name finally used by the framework is: global tablePrefix + the value of this annotation, for example: dev_document.
> - The usage of this annotation tab is the same as in Mybatis-Plus.
>

9
docs/en/index-shard.md Normal file
View File

@ -0,0 +1,9 @@
```java
/**
* Set the number of shards and replicas of the index
*
* @param shards number of shards
* @param replicas Number of replicas
*/
settings(Integer shards, Integer replicas);
```

11
docs/en/index.md Normal file
View File

@ -0,0 +1,11 @@
> The EE index module provides the following APIs for users to make convenient calls
> - indexName needs to be manually specified by the user
> - Object Wrapper is conditional constructor
```yaml
Boolean existsIndex(String indexName);
Boolean createIndex(LambdaEsIndexWrapper<T> wrapper);
Boolean updateIndex(LambdaEsIndexWrapper<T> wrapper);
Boolean deleteIndex(String indexName);
```
Please click the outline according to the name to enter the specific page to view the corresponding code of the interface

14
docs/en/insert.md Normal file
View File

@ -0,0 +1,14 @@
```java
// insert one record
Integer insert(T entity);
// batch insert
Integer insertBatch(Collection<T> entityList)
```
**Parameter Description**
| Type | Parameter name | Description |
| --- | --- | --- |
| T | entity | The entity that needs to be inserted |
| Collection<T> | entityList | The entity list that needs to be inserted |

5
docs/en/isNotNull.md Normal file
View File

@ -0,0 +1,5 @@
```java
isNotNull(R column)
isNotNull(boolean condition, R column)
```
● Field IS NOT NULL<br />● Example: isNotNull(Document::getTitle)--->title is not null

5
docs/en/isNull.md Normal file
View File

@ -0,0 +1,5 @@
```java
isNull(R column)
isNull(boolean condition, R column)
```
● Field IS NULL<br />● Example: isNull(Document::getTitle)--->title is null

5
docs/en/le.md Normal file
View File

@ -0,0 +1,5 @@
```java
le(R column, Object val)
le(boolean condition, R column, Object val)
```
● Less than or equal to <=<br />● Example: le("age", 18)--->age <= 18

5
docs/en/like.md Normal file
View File

@ -0,0 +1,5 @@
```java
like(R column, Object val)
like(boolean condition, R column, Object val)
```
● LIKE'%value%'<br />● Example: like("name", "James")--->name like'%James%'

5
docs/en/likeLeft.md Normal file
View File

@ -0,0 +1,5 @@
```java
likeLeft(R column, Object val)
likeLeft(boolean condition, R column, Object val)
```
● LIKE'% value'<br />● Example: likeLeft("name", "James")--->name like'%James'

5
docs/en/likeRight.md Normal file
View File

@ -0,0 +1,5 @@
```java
likeRight(R column, Object val)
likeRight(boolean condition, R column, Object val)
```
● LIKE'value%'<br />● Example: likeRight("name", "James")--->name like'James%'

11
docs/en/limit.md Normal file
View File

@ -0,0 +1,11 @@
```java
limit(Integer n);
limit(Integer m, Integer n);
```
● limit n is the maximum number of pieces of data returned, which is equivalent to n in limit n in MySQL, and the usage is the same.<br />● limit m,n skip m pieces of data and return n pieces of data at most, which is equivalent to limit m,n or offset m limit n in MySQL<br />● Example: limit(10)--->Only return up to 10 pieces of data<br />● Example: limit(2,5)--->Skip the first 2 pieces of data, start the query from the 3rd piece, and query 5 pieces of data in total
> **Tips:** If the n parameter is not specified, its default value is 10000
> If you do a single query and don't want too many low-scoring data, you need to manually specify n to limit it.
> In addition, the function of this parameter is consistent with the size and from in Es. It is only introduced for compatibility with MySQL syntax. Users can choose one of the two according to their own habits. When both are used, only one will take effect, and the later specified will override the first specified. of.

5
docs/en/lt.md Normal file
View File

@ -0,0 +1,5 @@
```java
lt(R column, Object val)
lt(boolean condition, R column, Object val)
```
● Less than <<br />● Example: lt("age", 18)--->age <18

7
docs/en/match.md Normal file
View File

@ -0,0 +1,7 @@
```java
match(R column, Object val)
match(boolean condition, R column, Object val)
```
> ● Word segment matching
> ● Example: match("content", "someone")--->content contains the keyword "someone". If the word segmentation granularity is set finer, someone may be split into "some" and "one". As long as the content contains "some" or "one", it can be searched out

5
docs/en/ne.md Normal file
View File

@ -0,0 +1,5 @@
```java
ne(R column, Object val)
ne(boolean condition, R column, Object val)
```
● Not equal to !=<br />● Example: ne("name", "Jimmy")--->name != 'Jimmy'

5
docs/en/notBetween.md Normal file
View File

@ -0,0 +1,5 @@
```java
notBetween(R column, Object val1, Object val2)
notBetween(boolean condition, R column, Object val1, Object val2)
```
● NOT BETWEEN value 1 AND value 2<br />● Example: notBetween("age", 18, 30)--->age not between 18 and 30

11
docs/en/notIn.md Normal file
View File

@ -0,0 +1,11 @@
```java
notIn(R column, Collection<?> value)
notIn(boolean condition, R column, Collection<?> value)
```
● Field not in (value.get(0), value.get(1), ...)<br />● Example: notIn("age",{1,2,3})--->age not in (1,2,3)
```java
notIn(R column, Object... values)
notIn(boolean condition, R column, Object... values)
```
● Field not in (v0, v1, ...)<br />● Example: notIn("age", 1, 2, 3)--->age not in (1,2,3)

5
docs/en/notLike.md Normal file
View File

@ -0,0 +1,5 @@
```java
notLike(R column, Object val)
notLike(boolean condition, R column, Object val)
```
● NOT LIKE'%value%'<br />● Example: notLike("name", "James")--->name not like'%James%'

10
docs/en/or.md Normal file
View File

@ -0,0 +1,10 @@
```java
or()
or(boolean condition)
```
● Note for splicing OR: Actively calling or means that the next method is not connected with and! (If you don't call or, the default is to connect with and)<br />● Example: eq("Document::getId",1).or().eq(Document::getTitle,"Hello")--->id = 1 or title ='Hello'
```java
or(Consumer<Param> consumer)
or(boolean condition, Consumer<Param> consumer)
```
● OR nesting<br />● Example: or(i -> i.eq(Document::getTitle, "Hello").ne(Document::getCreator, "Guy"))--->or (title ='Hello' and status != 'Guy' )

4
docs/en/orderBy.md Normal file
View File

@ -0,0 +1,4 @@
```java
orderBy(boolean condition, boolean isAsc, R... columns)
```
● Sorting: ORDER BY field, ...<br />● Example: orderBy(true, true, Document::getId,Document::getTitle)--->order by id ASC,title ASC

5
docs/en/orderByAsc.md Normal file
View File

@ -0,0 +1,5 @@
```java
orderByAsc(R... columns)
orderByAsc(boolean condition, R... columns)
```
● Sort: ORDER BY field, ... ASC<br />● Example: orderByAsc(Document::getId,Document::getTitle)--->order by id ASC,title ASC

5
docs/en/orderByDesc.md Normal file
View File

@ -0,0 +1,5 @@
```java
orderByDesc(R... columns)
orderByDesc(boolean condition, R... columns)
```
● Sorting: ORDER BY field, ... DESC<br />● Example: orderByDesc(Document::getId,Document::getTitle)--->order by id DESC,title DESC

11
docs/en/origin-query.md Normal file
View File

@ -0,0 +1,11 @@
```java
// Semi-native query
SearchResponse search(LambdaEsQueryWrapper<T> wrapper) throws IOException;
// Standard native query can specify RequestOptions
SearchResponse search(SearchRequest searchRequest, RequestOptions requestOptions) throws IOException;
```
> **Tips:**
> - In some high-level syntax, such as specifying the highlighted field, if our return type is the entity object itself, but there is usually no highlighted field in the entity, the highlighted field cannot be received. At this time, RestClietn's native return object SearchResponse can be used.
> - Although EE covers most of the scenarios where we use ES, there may still be scenarios that are not covered. At this time, you can still query through the native grammar provided by RestClient and call the standard native query method. Both input and return are RestClient native

18
docs/en/page.md Normal file
View File

@ -0,0 +1,18 @@
```java
// The return type is not specified, and the paging parameter is not specified (the current page is 1 by default, and the total number of queries is 10), suitable for queries with high-level grammar
PageInfo<SearchHit> pageQueryOriginal(LambdaEsQueryWrapper<T> wrapper) throws IOException;
// No return type specified, paging parameters specified, suitable for queries with high-level syntax
PageInfo<SearchHit> pageQueryOriginal(LambdaEsQueryWrapper<T> wrapper, Integer pageNum, Integer pageSize) throws IOException;
// 指定返回类型,但未指定分页参数(默认按当前页为1,总查询条数10条)
PageInfo<T> pageQuery(LambdaEsQueryWrapper<T> wrapper);
// Specify the return type and paging parameters
PageInfo<T> pageQuery(LambdaEsQueryWrapper<T> wrapper, Integer pageNum, Integer pageSize);
```
> **Tips:**
> - You can use paging query without integrating any plug-ins. This query belongs to physical paging.
> - In some high-level grammar usage scenarios, due to the return of highlighting, aggregation and other fields, it is recommended to use the native SearchHit to receive the result set. Otherwise, because the entity itself does not contain fields such as highlighting and aggregation, this type of Field is missing.
> - Note that PageInfo is provided by this framework. If you already have the most popular open source paging plugin [PageHelper](https://github.com/pagehelper/Mybatis-PageHelper) in your project, please be careful not to introduce errors when importing the package. EE uses the same return fields as PageHelper, so you don't need to worry about the field names. The extra workload caused by inconsistency.

12
docs/en/particple.md Normal file
View File

@ -0,0 +1,12 @@
> The word segmentation query is unique to Es. It is a query that is not supported in MySQL, that is, you can match according to keywords. There is not much introduction about word segmentation query. If you don't know it, please Google search to understand the concept, here only the usage is introduced.
```java
@Test
public void testMatch(){
LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();
String keyword = "w";
wrapper.match(Document::getContent,keyword);
List<Document> documents = documentMapper.selectList(wrapper);
System.out.println(documents);
}
```

226
docs/en/quick-start.md Normal file
View File

@ -0,0 +1,226 @@
We will use a simple Demo to illustrate the powerful functions of Easy-Es. Before that, we assume that you have
● Have a Java development environment and corresponding IDE
● Familiar with MySQL
● Familiar with Spring Boot
● Familiar with Maven
● Understand the basic concepts of Es
● Es is installed Recommended version 7.x+ (you can search for tutorials on Google if you don't have it, it is recommended to install another [es-head plugin](https://github.com/mobz/elasticsearch-head))
> **TIP**
> If you are too lazy to read the following tutorials, you can also download the [Springboo integrated demo](/en/demo.md) and run it directly
## Initialize the project
---
Create an empty Spring Boot project
> **TIP**
> You can use [Spring Initializer](https://start.spring.io/) to quickly initialize a Spring Boot project
## Add dependency
---
**Maven:**
```xml
<dependency>
<groupId>io.github.xpc1024</groupId>
<artifactId>easy-es-boot-starter</artifactId>
<version>Latest Version</version>
</dependency>
```
**Gradle:**
```groovy
compile group: 'io.github.xpc1024', name: 'easy-es-boot-starter', version: 'Latest Version'
```
> **Tips:** Latest Version: [Click here to get the latest version](https://img.shields.io/github/v/release/xpc1024/easy-es?include_prereleases&logo=xpc&style=plastic)
## Configuration
---
Add the necessary configuration of EasyEs in the application.yml configuration file:
```yaml
easy-es:
eanble: true # The default value is true, If the value of enable is false, it is considered that Easy-es is not enabled
address: 127.0.0.0:9200 # Your elasticsearch address,must contains port, If it is a cluster, please separate with',' just like this: 127.0.0.0:9200,127.0.0.1:9200
username: elastic # Es username, Not necessary, If it is not set in your elasticsearch, delete this line
password: WG7WVmuNMtM4GwNYkyWH # Es password, Not necessary, If it is not set, delete this line
```
> Other configurations can be omitted temporarily, the following chapters will introduce the configuration of EasyEs in detail
Add the @EsMapperScan annotation to the Spring Boot startup class to scan the Mapper folder:
```java
@SpringBootApplication
@EsMapperScan("com.xpc.easyes.sample.mapper")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
```
## backgrounds
---
There is currently a Document table. As the amount of data expands, its query efficiency can no longer meet product requirements. The table structure is as follows. We plan to migrate the content of this table to the Elasticsearch to improve query efficiency.
| id | title | content |
| --- | --- | --- |
## coding
---
Write the entity class Document.java ([Lombok](https://www.projectlombok.org/) is used here to simplify the code)
```java
@Data
public class Document {
/**
* just like the primary key in MySQL
*/
private String id;
/**
* title of document
*/
private String title;
/**
* content of document
*/
private String content;
/**
* creator of document
*/
private String creator;
}
```
> **Tips:** If there is no annotation and global configuration for the above field id, its strategy is automatically generated by Es by default. The corresponding field in es is'_id', and the field type is String. If you need to perform special processing on the id, it will be introduced in the subsequent chapters. How to configure Id.
Write the Mapper class DocumentMapper.java
```java
public interface DocumentMapper extends BaseEsMapper<Document> {
}
```
## Get started (CRUD)
---
Add test class to perform functional test:
> Pre-operation: Create an index (equivalent to a table in MySQL, must exists the table before subsequent CRUD)
```java
import com.xpc.easyes.core.enums.FieldType;
@SpringBootTest(classes = EasyEsApplication.class)
public class SearchTest {
@Resource
DocumentMapper documentMapper;
@Test
public void testCreatIndex() {
// Test to create an index If you dont understand the concept of Es index, please understand it first. A lazy man can be simply understood as a table in MySQL.
LambdaEsIndexWrapper<Document> wrapper = new LambdaEsIndexWrapper<>();
// For the sake of simplicity, use the class name as the index name directly. The following chapters will teach you how to configure and use the index more flexibly.
wrapper.indexName(Document.class.getSimpleName().toLowerCase());
// Here, the article title is mapped to the keyword type (word segmentation is not supported), and the document content is mapped to the text type (word segmentation query is supported)
wrapper.mapping(Document::getTitle, FieldType.KEYWORD)
.mapping(Document::getContent, FieldType.TEXT);
boolean isOk = documentMapper.createIndex(wrapper);
Assert.assertTrue(isOk);
// Expected value: true If it is true, it proves that the index has been successfully created
}
}
```
> **Test insert:** Add a new piece of data (equivalent to the Insert operation in MySQL)
```java
@Test
public void testInsert() {
// Test insert data
Document document = new Document();
document.setTitle("Hello");
document.setContent("World");
document.setCreator("Guy")
String id = documentMapper.insert(document);
System.out.println(id);
}
```
> Test query: query the specified data according to the conditions (equivalent to the Select operation in MySQL)
```java
@Test
public void testSelect() {
// test query
String title = "Hello";
LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();
wrapper.eq(Document::getTitle,title);
Document document = documentMapper.selectOne(wrapper);
System.out.println(document);
Assert.assertEquals(title,document.getTitle());
}
```
> Test update: update data (equivalent to the Update operation in MySQL)
```java
@Test
public void testUpdate() {
// There are two cases of update, which are demonstrated as follows:
// case1: Known id, update according to id (for the convenience of demonstration, this id is copied from the query in the previous step, the actual business can be queried by yourself)
String id = "krkvN30BUP1SGucenZQ9";
String title1 = "Nice";
Document document1 = new Document();
document1.setId(id);
document1.setTitle(title1);
documentMapper.updateById(document1);
// case2: id unknown, update according to conditions
LambdaEsUpdateWrapper<Document> wrapper = new LambdaEsUpdateWrapper<>();
wrapper.eq(Document::getTitle,title1);
Document document2 = new Document();
document2.setTitle("Bad");
documentMapper.update(document2,wrapper);
}
```
Through the update, the data title is first updated to Nice, and finally updated to Bad.
> Test delete: delete data (equivalent to the Delete operation in MySQL)
```java
@Test
public void testDelete() {
// There are two cases for deletion: delete according to id or delete according to conditions
// Considering that id deletion is too simple, here is only a demonstration of deletion based on conditions
LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();
String title = "Bad";
wrapper.eq(Document::getTitle,title);
int successCount = documentMapper.delete(wrapper);
System.out.println(successCount);
}
```
> **TIP**
> Please move to the complete code sample: [Easy-Es-Sample](https://github.com/xpc1024/easy-es/tree/main/easy-es-sample) (test directory)
> We are sorry that currently only the Chinese version is provided, but the code itself is the same
## summary
---
Through the above few simple steps, we have realized Document index creation and CRUD function
From the above steps, we can see that integrating Easy-Es is very simple, just import the starter project and configure the mapper scan path.
But the power of Easy-Es is far more than these functions. Want to learn more about the powerful functions of Easy-Es? Then continue browsing!

13
docs/en/sceen.md Normal file
View File

@ -0,0 +1,13 @@
1. Retrieval services
● Search Libraries<br />● E-commerce product search<br />● Massive system log retrieval
2. Question-and-answer service (essentially also a retrieval class)
● Online intelligent customer service<br />● Robots
3. Map services
● Taxi app<br />● Food delivery app<br />● Community group purchase and delivery<br />● Socializing with strangers
...<br />The above are just some application scenarios that I can think of. In fact, the API of Easy-Es basically covers more than 90% of the functions of Elastic Search and more than 99% of the common functions, so you can quickly build various systems based on EE, even if It is a very complex and changeable query, and you can also deal with it calmly, Trust me!

18
docs/en/select.md Normal file
View File

@ -0,0 +1,18 @@
```java
Long selectCount(LambdaEsQueryWrapper<T> wrapper);
T selectById(Serializable id);
List<T> selectBatchIds(Collection<? extends Serializable> idList);
// According to dynamic query conditions, query a record, if there are multiple records, will throw RuntimeException
T selectOne(LambdaEsQueryWrapper<T> wrapper);
// According to the dynamic query conditions, query all the records that meet the conditions
List<T> selectList(LambdaEsQueryWrapper<T> wrapper);
```
**Parameter Description**
| Type | Parameter name | Description |
| --- | --- | --- |
| Wrapper<T> | queryWrapper | Query parameter packaging class |
| Serializable | id | primary key in es |
| Collection<? extends Serializable> | idList | primary key list in es |

5
docs/en/set.md Normal file
View File

@ -0,0 +1,5 @@
```java
set(String column, Object val)
set(boolean condition, String column, Object val)
```
● SQL SET field<br />● Example: set(Document::getTitle, "new value")<br />● Example: set(Document::getTitle, "")--->database field value becomes an empty string<br />● Example: set(Document::getTitle, null)--->database field value becomes null

Some files were not shown because too many files have changed in this diff Show More