SpringBoot整合Easy-Es最佳實踐

文章目錄

    • 1.1 部署ES和Kibana
    • 1.2 SpringBoot整合ES及配置
      • 1.2.1 引入相關依賴
      • 1.2.2 YML相關配置
    • 1.3 索引CRUD
      • 1.3.1 索引托管自動擋
        • 1.3.1.1 配置實體模板
        • 1.3.1.2 配置啟動模式
      • 1.3.2 索引手動擋
        • 1.3.2.1 配置啟動模式
        • 1.3.2.2 配置實體模板
        • 1.3.2.3 創建索引
        • 1.3.2.4 查詢索引
        • 1.3.2.5 更新索引(不推薦)
        • 1.3.2.6 刪除索引
    • 1.4 數據CRUD
      • 1.4.1 數據同步
      • 1.4.2 數據CRUD
        • 1.4.2.1 新增數據
        • 1.4.2.2 刪除數據
        • 1.4.2.3 更新數據(不推薦)
        • 1.4.2.4 查詢數據(推薦分頁查詢)
      • 1.4.3 嵌套查詢
      • 1.4.4 鏈式調用
    • 1.5 拓展功能
      • 1.5.1 混合查詢
      • 1.5.2 分頁查詢
      • 1.5.3 排序
      • 1.5.4 分詞 / 模糊匹配
      • 1.5.5 條件過濾

Easy-Es官網: Easy-Es

1.1 部署ES和Kibana


參考部署ES及配置, 還有配置IK分詞器 跳轉鏈接: 部署ES及配置IK分詞器


1.2 SpringBoot整合ES及配置

1.2.1 引入相關依賴

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><exclusions><exclusion><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId></exclusion><exclusion><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-client</artifactId></exclusion><exclusion><groupId>org.elasticsearch</groupId><artifactId>elasticsearch</artifactId></exclusion></exclusions>
</dependency><!--ES相關-->
<dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId><version>7.14.0</version>
</dependency>
<dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-client</artifactId><version>7.14.0</version>
</dependency>
<dependency><groupId>org.elasticsearch</groupId><artifactId>elasticsearch</artifactId><version>7.14.0</version>
</dependency>
<dependency><groupId>org.dromara.easy-es</groupId><artifactId>easy-es-boot-starter</artifactId><version>2.0.0-beta4</version>
</dependency>

如果出現版本沖突就排除Spring管理的ES依賴

1.2.2 YML相關配置

# Easy-ES配置
easy-es:# 是否啟動(預先關閉)enable: true# es連接地址+端口 格式必須為ip:port,如果是集群則可用逗號隔開address: 192.168.164.128:9200# 如果無賬號密碼則可不配置此行#username:# 如果無賬號密碼則可不配置此行#password:# 默認為http 可缺省schema: http# 默認為true 打印banner 若您不期望打印banner,可配置為falsebanner: false# 心跳策略時間 單位:mskeep-alive-millis: 30000# 連接超時時間 單位:msconnect-timeout: 5000# 通信超時時間 單位:mssocket-timeout: 600000# 連接請求超時時間 單位:msconnection-request-timeout: 5000# 最大連接數 單位:個max-conn-total: 100# 最大連接路由數 單位:個max-conn-per-route: 100global-config:# 索引處理模式,smoothly:平滑模式, not_smoothly:非平滑模式, manual:手動模式,,默認開啟此模式process-index-mode: manual# 開啟控制臺打印通過本框架生成的DSL語句,默認為開啟,測試穩定后的生產環境建議關閉,以提升少量性能print-dsl: true# 當前項目是否分布式項目,默認為true,在非手動托管索引模式下,若為分布式項目則會獲取分布式鎖,非分布式項目只需synchronized鎖.distributed: false# 重建索引超時時間 單位小時,默認72H 可根據ES中存儲的數據量調整reindexTimeOutHours: 72# 異步處理索引是否阻塞主線程 默認阻塞 數據量過大時調整為非阻塞異步進行 項目啟動更快async-process-index-blocking: truedb-config:# 是否開啟下劃線轉駝峰 默認為falsemap-underscore-to-camel-case: true# 索引前綴,可用于區分環境  默認為空 用法和MP的tablePrefix一樣的作用和用法
#     index-prefix: template_# id生成策略 customize為自定義,id值由用戶生成,比如取MySQL中的數據id,如缺省此項配置,則id默認策略為es自動生成id-type: customize# 數據刷新策略,默認為不刷新,若對數據時效性要求比較高,可以調整為immediate,但性能損耗高,也可以調整為折中的wait_until
#     refresh-policy: immediate

1.3 索引CRUD

1.3.1 索引托管自動擋

1.3.1.1 配置實體模板
@Data
@IndexName(shardsNum = 3,replicasNum = 2) // 可指定分片數,副本數,若缺省則默認均為1
public class Document {/*** es中的唯一id,如果你想自定義es中的id為你提供的id,比如MySQL中的id,請將注解中的type指定為customize,如此id便支持任意數據類型)*/@IndexId(type = IdType.CUSTOMIZE)private Long id;/*** 文檔標題,不指定類型默認被創建為keyword_text類型,可進行精確查詢*/private String title;/*** 文檔內容,指定了類型及存儲/查詢分詞器*/@HighLight(mappingField="highlightContent")@IndexField(fieldType = FieldType.TEXT, analyzer = Analyzer.IK_SMART, searchAnalyzer = Analyzer.IK_MAX_WORD)private String content;/*** 作者 加@TableField注解,并指明strategy = FieldStrategy.NOT_EMPTY 表示更新的時候的策略為 創建者不為空字符串時才更新*/@IndexField(strategy = FieldStrategy.NOT_EMPTY)private String creator;/*** 創建時間*/@IndexField(fieldType = FieldType.DATE, dateFormat = "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis")private String gmtCreate;/*** es中實際不存在的字段,但模型中加了,為了不和es映射,可以在此類型字段上加上 注解@TableField,并指明exist=false*/@IndexField(exist = false)private String notExistsField;/*** 地理位置經緯度坐標 例如: "40.13933715136454,116.63441990026217"*/@IndexField(fieldType = FieldType.GEO_POINT)private String location;/*** 圖形(例如圓心,矩形)*/@IndexField(fieldType = FieldType.GEO_SHAPE)private String geoLocation;/*** 自定義字段名稱*/@IndexField(value = "wu-la")private String customField;/*** 高亮返回值被映射的字段*/private String highlightContent;
}

1.3.1.2 配置啟動模式
easy-es:socketTimeout: 600000 # 請求通信超時時間 單位:ms 默認值600000ms 在平滑模式下,由于要遷移數據,用戶可根據數據量大小調整此參數值大小,否則請求容易超時導致索引托管失敗,建議您盡量給大不給小,跟那玩意一樣,大點沒事,太小你懂的!global-config:process_index_mode: smoothly #smoothly:平滑模式, not_smoothly:非平滑模式, manual:手動模式async-process-index-blocking: true # 異步處理索引是否阻塞主線程 默認阻塞distributed: false # 項目是否分布式環境部署,默認為true, 如果是單機運行可填false,將不加分布式鎖,效率更高.reindexTimeOutHours: 72 # 重建索引超時時間 單位小時,默認72H 根據遷移索引數據量大小靈活指定

索引托管自動擋無需考慮索引的問題, 會根據模板類自動更新索引庫
若依框架不適配Easy-Es, 無法使用索引自動托管, 只能使用手動擋創建索引


1.3.2 索引手動擋

1.3.2.1 配置啟動模式
easy-es:global-config:process_index_mode: manual # 手動擋模式

1.3.2.2 配置實體模板
/*** 實體類信息
**/
@Data
@IndexName(shardsNum = 3, replicasNum = 2, keepGlobalPrefix = true)
public class Document {/*** es中的唯一id,如果你想自定義es中的id為你提供的id,比如MySQL中的id,請將注解中的type指定為customize或直接在全局配置文件中指定,如此id便支持任意數據類型)*/@IndexId(type = IdType.CUSTOMIZE)private String id;/*** 文檔標題,不指定類型默認被創建為keyword類型,可進行精確查詢*/private String title;/*** 文檔內容,指定了類型及存儲/查詢分詞器*/@HighLight(mappingField = "highlightContent")@IndexField(fieldType = FieldType.TEXT, analyzer = Analyzer.IK_SMART, searchAnalyzer = Analyzer.IK_MAX_WORD)private String content;// 省略其它字段...
}

1.3.2.3 創建索引
/*** 方式1*/
@Test
public void testCreateIndexByEntity() {// 絕大多數場景推薦使用 簡單至上documentMapper.createIndex();
}/*** 方式2*/
@Test
public void testCreateIndexByEntity() {// 適用于定時任務按日期創建索引場景String indexName = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));documentMapper.createIndex(indexName);
}
/*** 方式3*/
@Test
public void testCreateIndex() {// 復雜場景使用LambdaEsIndexWrapper<Document> wrapper = new LambdaEsIndexWrapper<>();// 此處簡單起見 索引名稱須保持和實體類名稱一致,字母小寫 后面章節會教大家更如何靈活配置和使用索引wrapper.indexName(Document.class.getSimpleName().toLowerCase());// 此處將文章標題映射為keyword類型(不支持分詞),文檔內容映射為text類型(支持分詞查詢)wrapper.mapping(Document::getTitle, FieldType.KEYWORD, 2.0f).mapping(Document::getLocation, FieldType.GEO_POINT).mapping(Document::getGeoLocation, FieldType.GEO_SHAPE).mapping(Document::getContent, FieldType.TEXT, Analyzer.IK_SMART, Analyzer.IK_MAX_WORD);// 0.9.8+版本,增加對符串字段名稱的支持,Document實體中須在對應字段上加上@Tablefield(value="wu-la")用于映射此字段值wrapper.mapping("wu-la", FieldType.TEXT, Analyzer.IK_MAX_WORD, Analyzer.IK_MAX_WORD);// 設置分片及副本信息,可缺省wrapper.settings(3, 2);// 設置別名信息,可缺省String aliasName = "daily";wrapper.createAlias(aliasName);// 設置父子信息,若無父子文檔關系則無需設置, 可缺省wrapper.join("joinField", "document", "comment");// 創建索引boolean isOk = documentMapper.createIndex(wrapper);Assertions.assertTrue(isOk);
}

1.3.2.4 查詢索引
@Test
public void testExistsIndex() {// 測試是否存在指定名稱的索引String indexName = Document.class.getSimpleName().toLowerCase();boolean existsIndex = documentMapper.existsIndex(indexName);Assertions.assertTrue(existsIndex);
}
@Test
public void testGetIndex() {GetIndexResponse indexResponse = documentMapper.getIndex();// 這里打印下索引結構信息 其它分片等信息皆可從indexResponse中取indexResponse.getMappings().forEach((k, v) -> System.out.println(v.getSourceAsMap()));
}

1.3.2.5 更新索引(不推薦)
@Test
public void testUpdateIndex() {// 測試更新索引LambdaEsIndexWrapper<Document> wrapper = new LambdaEsIndexWrapper<>();// 指定要更新哪個索引String indexName = Document.class.getSimpleName().toLowerCase();wrapper.indexName(indexName);wrapper.mapping(Document::getCreator, FieldType.KEYWORD);wrapper.mapping(Document::getGmtCreate, FieldType.DATE);boolean isOk = documentMapper.updateIndex(wrapper);Assertions.assertTrue(isOk);
}

1.3.2.6 刪除索引
@Test
public void testDeleteIndex() {// 指定要刪除哪個索引String indexName = Document.class.getSimpleName().toLowerCase();boolean isOk = documentMapper.deleteIndex(indexName);Assertions.assertTrue(isOk);
}

1.4 數據CRUD

1.4.1 數據同步

參考RestClient操作, 使用MQ做異步通知來同步MYSQLES的數據
跳轉鏈接: RestClient操作


1.4.2 數據CRUD

1.4.2.1 新增數據
// 插入一條記錄,默認插入至當前mapper對應的索引
Integer insert(T entity);
// 插入一條記錄 可指定具體插入的索引,多個用逗號隔開
Integer insert(T entity, String... indexNames);// 批量插入多條記錄
Integer insertBatch(Collection<T> entityList)
// 批量插入多條記錄 可指定具體插入的索引,多個用逗號隔開 
Integer insertBatch(Collection<T> entityList, String... indexNames);

  • 如果您在insert時傳入的entity有id并且該id對應數據已存在,則此次insert實際效果為更新該id對應的數據,并且更新不計入insert接口最后返回的成功總條數.
  • 當insert接口如上所述,觸發了數據更新邏輯,本次更新字段和全局配置的策略(如NOT_NULL/NOT_EMPTY)等均不生效,若您期望策略生效,可以調用update接口而非insert接口.
  • 插入后如需id值可直接從entity中取,用法和MP中一致,批量插入亦可直接從原對象中獲取插入成功后的數據id,以上接口返回Integer為成功條數.

1.4.2.2 刪除數據
// 根據 ID 刪除
Integer deleteById(Serializable id);
// 根據 ID 刪除 可指定具體的索引,多個用逗號隔開 
Integer deleteById(Serializable id, String... indexNames);// 根據 entity 條件,刪除記錄
Integer delete(LambdaEsQueryWrapper<T> wrapper);// 刪除(根據ID 批量刪除)
Integer deleteBatchIds(Collection<? extends Serializable> idList);
// 刪除(根據ID 批量刪除)可指定具體的索引,多個用逗號隔開 
Integer deleteBatchIds(Collection<? extends Serializable> idList, String... indexNames);

1.4.2.3 更新數據(不推薦)

在傳入的entity中帶上id, 可以和新增使用同一份接口, 省事~

//根據 ID 更新
Integer updateById(T entity);
//根據 ID 更新 可指定具體的索引,多個用逗號隔開 
Integer updateById(T entity, String... indexNames);// 根據ID 批量更新
Integer updateBatchByIds(Collection<T> entityList);
//根據 ID 批量更新 可指定具體的索引,多個用逗號隔開 
Integer updateBatchByIds(Collection<T> entityList, String... indexNames);// 根據動態條件 更新記錄
Integer update(T entity, LambdaEsUpdateWrapper<T> updateWrapper);

1.4.2.4 查詢數據(推薦分頁查詢)
// 獲取總數
Long selectCount(LambdaEsQueryWrapper<T> wrapper);
// 獲取總數 distinct為是否去重 若為ture則必須在wrapper中指定去重字段
Long selectCount(Wrapper<T> wrapper, boolean distinct);// 根據 ID 查詢 
T selectById(Serializable id);
// 根據 ID 查詢 可指定具體的索引,多個用逗號隔開 
T selectById(Serializable id, String... indexNames);
// 查詢(根據ID 批量查詢)
List<T> selectBatchIds(Collection<? extends Serializable> idList);
// 查詢(根據ID 批量查詢)可指定具體的索引,多個用逗號隔開 
List<T> selectBatchIds(Collection<? extends Serializable> idList, String... indexNames);
// 根據動態查詢條件,查詢一條記錄 若存在多條記錄 會報錯
T selectOne(LambdaEsQueryWrapper<T> wrapper);
// 根據動態查詢條件,查詢全部記錄
List<T> selectList(LambdaEsQueryWrapper<T> wrapper);

1.4.3 嵌套查詢

/*** 場景一: 嵌套and的使用 */
@Test
public void testNestedAnd() {// 下面查詢條件等價于MySQL中的 select * from document where star_num in (1, 2) and (title = '老漢' or title = '推*')LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();wrapper.in(Document::getStarNum, 1, 2).and(w -> w.eq(Document::getTitle, "老漢").or().eq(Document::getTitle, "推*"));List<Document> documents = documentMapper.selectList(wrapper);
}
/*** 場景二: 拼接and的使用 */
@Test
public void testAnd(){// 下面查詢條件等價于MySQL中的 select * from document where title = '老漢' and content like '推*'// 拼接and比較特殊,因為使用場景最多,所以條件與條件之間默認就是拼接and,所以可以直接省略,這點和MP是一樣的LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();wrapper.eq(Document::getTitle, "老漢").match(Document::getContent, "推*");List<Document> documents = documentMapper.selectList(wrapper);
}/*** 場景二: 嵌套or的使用 */
@Test
public void testNestedOr() {// 下面查詢條件等價于MySQL中的 select * from document where star_num = 1 or (title = '老漢' and creator = '糟老頭子')LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();wrapper.eq(Document::getStarNum, 1).or(i -> i.eq(Document::getTitle, "老漢").eq(Document::getCreator, "糟老頭子"));List<Document> documents = documentMapper.selectList(wrapper);
}
/*** 場景三: 拼接or的使用 */
@Test
public void testOr() {// 下面查詢條件等價于MySQL中的 select * from document where title = '老漢' or title = '癡漢'LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();wrapper.eq(Document::getTitle, "老漢").or().eq(Document::getTitle, "癡漢");List<Document> documents = documentMapper.selectList(wrapper);
}
/*** 場景四: 嵌套filter的使用 其實和場景一一樣,只不過filter中的條件不計算得分,無法按得分排序,查詢性能稍高*/
@Test
public void testNestedFilter() {// 下面查詢條件等價于MySQL中的 select * from document where star_num in (1, 2) and (title = '老漢' or title = '推*')LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();wrapper.in(Document::getStarNum, 1, 2).filter(w -> w.eq(Document::getTitle, "老漢").or().eq(Document::getTitle, "推*"));List<Document> documents = documentMapper.selectList(wrapper);
}/*** 場景五: 拼接filter的使用 filter中的條件不計算得分,無法按得分排序,查詢性能稍高*/
@Test
public void testFilter() {// 下面查詢條件等價于MySQL中的 select * from document where title = '老漢'LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();wrapper.filter().eq(Document::getTitle, "老漢");List<Document> documents = documentMapper.selectList(wrapper);
}/*** 場景六: 嵌套mustNot的使用 */
@Test
public void testNestedNot() {// 下面查詢條件等價于MySQL中的 select * from document where title = '老漢' and (size != 18 and age != 18)LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();wrapper.eq(Document::getTitle, "老漢").not(i->i.eq(size,18).eq(age,18));List<Document> documents = documentMapper.selectList(wrapper);
}/*** 場景六: 拼接not()的使用*/
@Test
public void testNot() {// 下面查詢條件等價于MySQL中的 select * from document where title = '老漢' and  size != 18LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();wrapper.eq(Document::getTitle, "老漢").not().eq(size,18);List<Document> documents = documentMapper.selectList(wrapper);
}

1.4.4 鏈式調用

// 索引鏈式構造器
LambdaEsIndexChainWrapper<T> lambdaChainIndex(BaseEsMapper<T> baseEsMapper);
// 查詢鏈式構造器
LambdaEsQueryChainWrapper<T> lambdaChainQuery(BaseEsMapper<T> baseEsMapper);
// 更新(含刪除)鏈式構造器
LambdaEsUpdateChainWrapper<T> lambdaChainUpdate(BaseEsMapper<T> baseEsMapper);
@Test
public void testOne() {// 隔壁老漢寫的鏈式調用Document document = EsWrappers.lambdaChainQuery(documentMapper).eq(Document::getTitle, "隔壁老漢").one();
}    
@Test
public void testSelectOne() {// 隔壁老王寫的半吊子鏈式調用LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();wrapper.eq(Document::getTitle, "隔壁老王").limit(1);Document document = documentMapper.selectOne(wrapper);
}

1.5 拓展功能

1.5.1 混合查詢

/*** 正確使用姿勢0(最實用,最簡單,最推薦的使用姿勢):EE滿足的語法,直接用,不滿足的可以構造原生QueryBuilder,然后通過wrapper.mix傳入QueryBuilder* @since 2.0.0-beta2 2.0.0-beta2才正式引入此方案,此方案為混合查詢的最優解決方案,由于QueryBuilder涵蓋了ES中全部的查詢,所以通過此方案* 理論上可以處理任何復雜查詢,并且可以和EE提供的四大嵌套類型無縫銜接,徹底簡化查詢,解放生產力!*/
@Test
public void testMix0(){// 查詢標題為老漢,內容匹配 推*,且最小匹配度不低于80%的數據// 當前我們提供的開箱即用match并不支持設置最小匹配度,此時就可以自己去構造一個matchQueryBuilder來實現LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();QueryBuilder queryBuilder = QueryBuilders.matchQuery("content", "推*").minimumShouldMatch("80%");wrapper.eq(Document::getTitle,"老漢").mix(queryBuilder);List<Document> documents = documentMapper.selectList(wrapper);System.out.println(documents);
}
/*** 混合查詢正確使用姿勢1: EE提供的功能不支持某些過細粒度的功能,所有查詢條件通過原生語法構造,僅利用EE提供的數據解析功能*/
@Test
public void testMix1() {// RestHighLevelClient原生語法SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();searchSourceBuilder.query(QueryBuilders.matchQuery("content", "推*").minimumShouldMatch("80%"));// 僅利用EE查詢并解析數據功能LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();wrapper.setSearchSourceBuilder(searchSourceBuilder);List<Document> documents = documentMapper.selectList(wrapper);System.out.println(documents);
}

1.5.2 分頁查詢

// 物理分頁
EsPageInfo<T> pageQuery(LambdaEsQueryWrapper<T> wrapper, Integer pageNum, Integer pageSize);
@Test
public void testPageQuery() {LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();wrapper.match(Document::getTitle, "老漢");EsPageInfo<Document> documentPageInfo = documentMapper.pageQuery(wrapper,1,10);System.out.println(documentPageInfo);
}

1.5.3 排序

// 降序排列
wrapper.orderByDesc(排序字段,支持多字段)// 升序排列
wrapper.orderByAsc(排序字段,支持多字段)// 根據得分排序(此功能0.9.7+版本支持;不指定SortOrder時默認降序,得分高的在前,支持升序/降序)
wrapper.sortByScore(boolean condition,SortOrder sortOrder)

1.5.4 分詞 / 模糊匹配

@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 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);
}

1.5.5 條件過濾

/*** 場景五: 拼接filter的使用 filter中的條件不計算得分,無法按得分排序,查詢性能稍高*/
@Test
public void testFilter() {// 下面查詢條件等價于MySQL中的 select * from document where title = '老漢'LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();wrapper.filter().eq(Document::getTitle, "老漢");List<Document> documents = documentMapper.selectList(wrapper);
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/42540.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/42540.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/42540.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【INTEL(ALTERA)】為什么在設計遷移后,無法在Nios II BSP 編輯器中找到 DDR3 作為內存區域

目錄 說明 解決方法 說明 將設計從 Quartus II 14.1 及以下遷移到 Quartus prime 17.0 時&#xff0c;DDR3 不再被識別為Nios II BSP 編輯器區域中的內存區域。 解決方法 遷移設計后&#xff0c;從 Qsys 設計中移除 DDR3 IP&#xff0c;然后將其再次添加。生成 Qsys 文件后…

車牌號查車輛信息-車牌號查車輛信息接口-汽車API接口

接口簡介&#xff1a;輸入車牌號&#xff0c;返回車輛相關信息&#xff08;無車主信息&#xff09;。初始登記日期、上險日期、保險到期時間、車架號、品牌這些數據會返回&#xff0c;其他數據不一定全部返回&#xff0c;,詳細參數請查看返回接口文檔 一般在新車上險或過戶后第…

微信小程序消息通知(一次訂閱)

在微信公眾平臺配置通知模版 通過wx.login獲取code發送給后端 let that this // 登陸codewx.login({success: function (res) {if (res.code) {// 發送code到后端換取openid和session_keythat.setData({openCode: res.code})console.log(that.data.openCode, openCode);// 調…

數學系C++(六七)

目錄 * &指針與地址 void指針 指針可以等于&#xff1a; const 指向常量的指針 const int *px 常指針 int * const px 指向常量的常指針const 類型標識符 * const 指針名 指針加減&#xff1a; 指針恒等式 函數指針【待續】 指針型函數&#xff1a; 指向函數的…

大數據之路 讀書筆記 Day4 數據同步

回顧&#xff1a; Day 3 總結了無限客戶端的日志采集 大數據之路 讀書筆記 Day 3Day 2總結了瀏覽器端的日志采集 大數據之路 讀書筆記 Day 2 數據同步 阿里數據體系中的數據同步&#xff0c;主要指的是在不同的數據存儲系統之間進行數據的傳輸與更新&#xff0c;以保證數據的一…

【代碼隨想錄_Day26】56 合并區間 738 單調遞增的數字

Day26 OK&#xff0c;今日份的打卡&#xff01;第二十六天 以下是今日份的總結合并區間單調遞增的數字 以下是今日份的總結 56 合并區間 738 單調遞增的數字 今天的題目難度不低&#xff0c;盡量還是寫一些簡潔代碼 ^?_?^ 合并區間 思路&#xff1a; 先排序&#xff0c;按…

reactor和proactor模型

Reactor模型是非阻塞的同步IO模型。在主線程中也就是IO處理單元中&#xff0c;只負責監聽文件描述符上是否有事件發生&#xff0c;有的話就立即將事件通知工作線程&#xff0c;將socket可讀可寫事件放入請求隊列&#xff0c;交給工作線程處理。 總而言之就是主線程監聽有事件發…

apk反編譯修改教程系列-----修改apk 解除軟件限制功能 實例操作步驟解析_3【二十二】

在前面的幾期博文中有過解析去除apk中功能權限的反編譯步驟。另外在以往博文中也列舉了修改apk中選項功能權限的操作方法。今天以另外一款apk作為演示修改反編譯去除軟件功能限制的步驟。興趣的友友可以參考其中的修改過程。 課程的目的是了解apk中各個文件的具體作用以及簡單…

debain系統使用日志

賬號 vboxuser changeme ssh遠程登錄vbox虛擬機 https://www.cnblogs.com/BuzzWeek/p/17557981.html Terminal su - root changeme sudo apt-get update sudo apt-get -y install openssh-server #啟動sshd systemctl status sshd 設置允許ssh登錄vbox虛擬機 參考&#xf…

【密碼學】什么是密碼?什么是密碼學?

一、密碼的定義 根據《中華人民共和國密碼法》對密碼的定義如下&#xff1a; 密碼是指采用特定變換的方法對信息等進行加密保護、安全認證的技術、產品和服務。 二、密碼學的定義 密碼學是研究編制密碼和破譯密碼的技術科學。由定義可以知道密碼學分為兩個主要分支&#x…

69.WEB滲透測試-信息收集- WAF、框架組件識別(9)

免責聲明&#xff1a;內容僅供學習參考&#xff0c;請合法利用知識&#xff0c;禁止進行違法犯罪活動&#xff01; 內容參考于&#xff1a; 易錦網校會員專享課 上一個內容&#xff1a;68.WEB滲透測試-信息收集- WAF、框架組件識別&#xff08;8&#xff09; 有無waf存在&am…

GESP C++一級真題

PDF圖片1-7 點贊??關注&#x1f60d;收藏?? 互粉必回&#x1f64f;&#x1f64f;&#x1f64f;

DPDK源碼分析之(1)libmbuf模塊

DPDK源碼分析之(1)libmbuf模塊 Author&#xff1a;OnceDay Date&#xff1a;2024年7月2日 漫漫長路&#xff0c;有人對你笑過嘛… 全系列文檔可參考專欄&#xff1a;源碼分析_Once-Day的博客-CSDN博客 參考文檔&#xff1a; DPDK downloadGetting Started Guide for Linux…

JAVA中的for-each(增強型for循環)

Java 8及之后的版本中與for-each循環&#xff08;也稱為增強型for循環&#xff09;和數組處理結合使用時&#xff0c;它可能類似于Lambda表達式或流&#xff08;Stream&#xff09;API中的上下文。 舉例&#xff1a; public class ArrLength {public static void main(String…

CGAL計算凸包(OSG進行可視化)

目錄 一、什么是凸包 二、運行步驟 1、安裝依賴項 2、編譯osg庫 3、運行代碼 4、運行截圖 一、什么是凸包 凸包是計算幾何中的一個基本概念,用來描述一個點集的最小凸包圍形。具體來說,給定一個點集,凸包是包含該點集的最小凸多邊形或凸多面體。 二維凸包:在二維平面…

迭代器模式在金融業務中的應用及其框架實現

引言 迭代器模式&#xff08;Iterator Pattern&#xff09;是一種行為設計模式&#xff0c;它提供了一種方法順序訪問一個聚合對象中的各個元素&#xff0c;而又不需要暴露該對象的內部表示。在金融業務中&#xff0c;迭代器模式可以用于遍歷復雜的數據結構&#xff0c;如交易…

算法-常見數據結構設計

文章目錄 1. 帶有setAll功能的哈希表2. LRU緩存結構3. O(1)時間插入刪除隨機(去重)4. O(1)時間插入刪除隨機(不去重)5. 快速獲取數據流中的中位數6. 最大頻率棧7. 全O(1)結構8. LFU緩存結構 本節的內容比較難, 大多是leetcodeHard難度級別的題目 1. 帶有setAll功能的哈希表 哈希…

js計算兩個日期直接的間隔天,2018/12/14到2017/11/10有多少天

const startDate new Date(2017-11-10)const endDate new Date(2018-12-14)const diffTime Math.abs(endDate - startDate)const diffDays Math.ceil(diffTime / (1000 * 60 * 60 * 24))console.log(diffDays) // 輸出天數差 人工智能學習網站 https://chat.xutongbao.top…

解析Java中1000個常用類:DoubleSummaryStatistics類,你學會了嗎?

在線工具站 推薦一個程序員在線工具站:程序員常用工具(http://cxytools.com),有時間戳、JSON格式化、文本對比、HASH生成、UUID生成等常用工具,效率加倍嘎嘎好用。程序員資料站 推薦一個程序員編程資料站:程序員的成長之路(http://cxyroad.com),收錄了一些列的技術教程…

VSCode神仙插件——Codeium (AI編程助手)

1、安裝&登錄插件 安裝過程中會讓你登錄Codeium賬戶&#xff0c;可以通過Google賬戶登錄&#xff0c;或者可以注冊一個Codeium賬戶&#xff08;如果沒有彈出讓你登錄賬戶的界面&#xff0c;可以等安裝結束后在右下角找到登錄的地方&#xff09; 右下角顯示如下圖所示&#…