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 , 它们都是 ...
随机推荐
- 【USACO 2021 February Contest, Platinum】Problem 1 No Time to Dry
\(\text{Solution}\) 一个点可与另一个颜色相同点同时涂色当且仅当两点间颜色都大于等于这两点 那么我们可以预处理一个点向左向右最远能到的位置,记为 \(l_i,r_i)\) 当 \(l ...
- JZOJ 5350. 【NOIP2017提高A组模拟9.7】陶陶摘苹果
题目 分析 很神奇的事情又发生了!! 很容易想到设 \(f_{i,j}\) 表示考虑前 \(i\) 个区间,已选 \(j\) 个区间且必选第 \(i\) 时能覆盖到的最多苹果数 转移 \(O(n)\) ...
- DrCush_0813_风湿性疾病, 药物和新冠指南
风湿性疾病, 药物和新冠指南 原文网址: https://rheumnow.com/news/rheumatic-diseases-drugs-and-covid-19-guidelines Jack ...
- PostgreSQL建立索引时,如何避免写数据锁定
先介绍一下Postgresql的建索引语法: CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] [ name ] ON table [ USING method ] ( ...
- Git介绍下载安装以及基本使用
目录 一.git介绍 二.下载安装git软件 三.基本使用 四.制作忽略文件 五.Git.Gitee.GitHub.Gitlab.bitbucket的区别 六.基础代码操作分类 一.git介绍 git ...
- torch.nn.Embedding使用详解
torch.nn.Embedding: 随机初始化词向量,词向量值在正态分布N(0,1)中随机取值.输入:torch.nn.Embedding(num_embeddings, – 词典的大小尺寸,比如 ...
- Kotlin学习-基础知识点
一:基础要点 //常量定义 valval arg_a1: Int = 1 //变量定义varvar arg_a2 = 5 // 系统自动推断变量类型为Int备注:kotlin 定义变量必须给定初始 ...
- js中各种事件监听
html.push('<input type="button" id="autocount_' + sysTime + '" class="la ...
- [数据库-Mongo总结]-mysql使用总结和pymysql交互
3. MySQL 3.1 安装 3.1.1 win 3.1.1.1 安装 >下载mysql >mysql-front: Host:localhost 端口:3306 用户:root 3.1 ...
- docker配置文件模板
{ "registry-mirrors": [ "https://bxsfpjcb.mirror.aliyuncs.com" ], "max-conc ...