Elasticsearch 实战
需求
假设现在有这么一个需求,系统接了很多的报文,需要提供全文检索,为了简化,报文目前只有类型,流水号,内容这三个字段。
索引设计
建立msg索引,映射规则如下
PUT /msg
{
"mappings" : {
"properties" : {
"traceNo" : {
"type" : "keyword"
},
"type" : {
"type" : "keyword"
},
"content" : {
"type" : "text"
}
}
}
}
代码实现
交易VO
@Getter
@Setter
public class TradeVO {
/**
* 交易编号
*/
private String tradeNo;
/**
* 成交金额
*/
private Integer matchAmt;
/**
* 成交数量
*/
private Integer matchQty;
}
报文实体
package com.wangtao.msgsearch.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Msg {
/**
* 0001: 交易所报文
* 0002: 银行间报文
* 0003: 场外报文
* es类型: keyword
*/
private String type;
/**
* 流水号
* es类型: keyword
*/
private String traceNo;
/**
* 报文内容
* es类型: text
*/
private String content;
}
查询VO
package com.wangtao.msgsearch.vo;
import lombok.Data;
@Data
public class MsgSearchVO {
/**
* 报文类型
*/
private String type;
/**
* 流水号
*/
private String traceNo;
/**
* 关键字, 从报文内容搜索
*/
private String keyword;
private Integer pageNo = 1;
private Integer pageSize = 20;
}
索引创建
/**
* 创建索引并指定映射
*/
@GetMapping("/createIndex")
public void createIndex() throws IOException {
TypeMapping typeMapping = new TypeMapping.Builder()
.properties("type", p -> p.keyword(k -> k))
.properties("traceNo", p -> p.keyword(k -> k))
.properties("content", p -> p.text(t -> t))
.build();
CreateIndexRequest createIndexRequest = new CreateIndexRequest.Builder()
.index(INDEX_NAME)
.mappings(typeMapping)
.build();
BooleanResponse booleanResponse = elasticsearchClient.indices().exists(e -> e.index(INDEX_NAME));
if (booleanResponse.value()) {
// 如果存在则删除
elasticsearchClient.indices().delete(d -> d.index(INDEX_NAME));
}
elasticsearchClient.indices().create(createIndexRequest);
}
插入测试数据
/**
* 准备数据
*/
private List<Msg> generateData() {
Random random = new Random();
List<Msg> msgList = new ArrayList<>();
for (int i = 1; i <= 50; i++) {
TradeVO tradeVO = new TradeVO();
tradeVO.setTradeNo("T20220821" + String.format("%03d", i));
tradeVO.setMatchAmt(random.nextInt(10000));
tradeVO.setMatchQty(tradeVO.getMatchAmt());
Msg msg = new Msg();
msg.setTraceNo("M20220821" + String.format("%03d", i));
msg.setType(MsgTypeEnum.ofOrdinal(i % 3).getValue());
try {
msg.setContent(objectMapper.writeValueAsString(tradeVO));
} catch (JsonProcessingException e) {
e.printStackTrace();
}
msgList.add(msg);
}
return msgList;
}
/**
* 批量插入数据
*/
@GetMapping("/addData")
public List<Msg> addData() throws IOException {
List<Msg> msgList = generateData();
List<BulkOperation> bulkOperations = new ArrayList<>();
for (int i = 1; i <= msgList.size(); i++) {
Msg msg = msgList.get(i - 1);
String finalI = i + "";
BulkOperation bulkOperation = new BulkOperation.Builder()
.index(o -> o.id(finalI).document(msg))
.build();
bulkOperations.add(bulkOperation);
}
BulkRequest bulkRequest = new BulkRequest.Builder()
.index(INDEX_NAME)
.operations(bulkOperations)
.build();
BulkResponse response = elasticsearchClient.bulk(bulkRequest);
if (response.errors()) {
log.error("batch insert has error!");
}
return msgList;
}
根据条件搜索
@PostMapping("/searchByCondition")
public List<Msg> searchByCondition(@RequestBody MsgSearchVO msgSearchVO) throws IOException {
/*
* 类型为keyword时, 记录建立倒排索引时不会进行分词
* 查询时使用term关键字, 条件不会被分词
*
* 类型为text时, 记录建立倒排索引时会进行分词
* 查询时使用match关键字, 条件也会被分词
*/
log.info("args: {}", msgSearchVO);
Integer from = (msgSearchVO.getPageNo() - 1) * msgSearchVO.getPageSize();
List<Query> andQueryList = new ArrayList<>();
if (StringUtils.isNotBlank(msgSearchVO.getType())) {
Query byType = new TermQuery.Builder()
.field("type")
.value(msgSearchVO.getType())
.build()._toQuery();
andQueryList.add(byType);
}
if (StringUtils.isNotBlank(msgSearchVO.getTraceNo())) {
Query byTraceNo = new TermQuery.Builder()
.field("traceNo")
.value(msgSearchVO.getTraceNo())
.build()._toQuery();
andQueryList.add(byTraceNo);
}
if (StringUtils.isNotBlank(msgSearchVO.getKeyword())) {
Query byContent = new MatchQuery.Builder()
.field("content")
.query(msgSearchVO.getKeyword())
.build()._toQuery();
andQueryList.add(byContent);
}
Query query = new BoolQuery.Builder()
.must(andQueryList)
.build()._toQuery();
SearchResponse<Msg> response = elasticsearchClient.search(
s -> s.index(INDEX_NAME).from(from).size(msgSearchVO.getPageSize())
.query(query),
Msg.class
);
List<Hit<Msg>> hits = response.hits().hits();
assert response.hits().total() != null;
log.info("page count: {}", hits.size());
log.info("total count: {}", response.hits().total().value());
return hits.stream().map(Hit::source).collect(Collectors.toList());
}
源码
https://github.com/wangtaoj/elasticsearch-learning
Elasticsearch 实战的更多相关文章
- ElasticSearch实战-入门
http://www.cnblogs.com/smartloli/ 1.概述 今天接着<ElasticSearch实战-日志监控平台>一文来给大家分享后续的学习,在<ElasticS ...
- ElasticSearch实战-日志监控平台
1.概述 在项目业务倍增的情况下,查询效率受到影响,这里我们经过讨论,引进了分布式搜索套件——ElasticSearch,通过分布式搜索来解决当下业务上存在的问题.下面给大家列出今天分析的目录: El ...
- ElasticSearch实战
ElasticSearch实战-入门 1.概述 今天接着<ElasticSearch实战-日志监控平台>一文来给大家分享后续的学习,在<ElasticSearch实战-日志监控平台& ...
- ElasticSearch实战-编码实践
1.概述 前面在<ElasticSearch实战-入门>中给大家分享如何搭建这样一个集群,在完成集群的搭建后,今天给大家分享如何实现对应的业务功能模块,下面是今天的分享内容,目录如下所示: ...
- I-team 博客全文检索 Elasticsearch 实战
一直觉得博客缺点东西,最近还是发现了,当博客慢慢多起来的时候想要找一篇之前写的博客很是麻烦,于是作为后端开发的楼主觉得自己动手丰衣足食,也就有了这次博客全文检索功能Elasticsearch实战,这里 ...
- ElasticSearch实战系列二: ElasticSearch的DSL语句使用教程---图文详解
前言 在上一篇中介绍了ElasticSearch集群和kinaba的安装教程,本篇文章就来讲解下 ElasticSearch的DSL语句使用. ElasticSearch DSL 介绍 Elastic ...
- ElasticSearch实战系列三: ElasticSearch的JAVA API使用教程
前言 在上一篇中介绍了ElasticSearch实战系列二: ElasticSearch的DSL语句使用教程---图文详解,本篇文章就来讲解下 ElasticSearch 6.x官方Java API的 ...
- ElasticSearch实战系列四: ElasticSearch理论知识介绍
前言 在前几篇关于ElasticSearch的文章中,简单的讲了下有关ElasticSearch的一些使用,这篇文章讲一下有关 ElasticSearch的一些理论知识以及自己的一些见解. 虽然本人是 ...
- ElasticSearch实战系列五: ElasticSearch的聚合查询基础使用教程之度量(Metric)聚合
Title:ElasticSearch实战系列四: ElasticSearch的聚合查询基础使用教程之度量(Metric)聚合 前言 在上上一篇中介绍了ElasticSearch实战系列三: Elas ...
- ElasticSearch实战系列六: Logstash快速入门和实战
前言 本文主要介绍的是ELK日志系统中的Logstash快速入门和实战 ELK介绍 ELK是三个开源软件的缩写,分别表示:Elasticsearch , Logstash, Kibana , 它们都是 ...
随机推荐
- JZOJ 4250.路径
\(\text{Solution}\) \(30\) 分暴搜合法路径 另 \(30\) 分状压 设 \(f_{i,j,k}\) 表示当前到第 \(i\) 个点,走过的点状态为 \(j\),走过的路径长 ...
- 在线工具帮助医生在社区转诊时甄别SpA患者
在线工具帮助医生在社区转诊时甄别SpA患者 Habibi S, et al. Rheumatology 2016. Present ID: 202. 背景:目前已开发了多种转诊策略以优化脊柱关节炎(S ...
- Qt-FFmpeg开发-视频播放【软解码】(1)
Qt-FFmpeg开发-视频播放[软解码] 目录 Qt-FFmpeg开发-视频播放[软解码] 1.概述 2.实现效果 3.FFmpeg软解码流程 4.主要代码 6.完整源代码 更多精彩内容 个人内容分 ...
- Linux常用命令 转于WoW_Boom
一.常用命令 1.进入到用户根目录cd ~ 或 cd 2.查看当前所在目录pwd 3.进入到itcast用户根目录cd ~itcast 4.返回到原来目录cd - 5.返回到上一级目录cd .. 6. ...
- javaSE学习二
使用Scanner实现用户交互 注意点:使用next方法时一定读取到有效字符后才能结束输入,有效字符前的空白自动去除,有效字符后的空白为结束符,next不能得到有空格的字符串. nextline方法以 ...
- MySQL-存储引擎-索引
事务 方式1:set @@autocommit = 0 -- 将事务提交方式设置为手动 方式2:start transaction -- 开启事务 事务四大特性ACID: A:原子性(Atomicit ...
- ifconfig查询的时候,只有lo网卡,没有ens33网卡
问题ifconfig查询的时候,只有lo网卡,但是ifconfig -a查询的时候却有ens33网卡ls /etc/syconfig/network-scripts/查找所有网卡配置信息文件的时候,没 ...
- Oracle 查看表空间使用率
SELECT Upper(F.TABLESPACE_NAME) "TablespaceName", D.TOT_GROOTTE_MB "Total(M)", D ...
- Unity打包xcode修改工程配置代码
1 using System.IO; 2 using UnityEngine; 3 using UnityEditor; 4 using UnityEditor.iOS.Xcode; 5 using ...
- web基础(3):CSS样式
chapter4 CSS样式 html是网页的内容和结构:CSS是网页的样式.内容和样式相分离,便于修改样式. CSS cascading style sheets 层叠样式表.一个内容上面可以添加多 ...