ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Elasticsearch 实战

2022-08-21 22:03:59  阅读:219  来源: 互联网

标签:实战 msgSearchVO keyword 报文 private Elasticsearch new type


需求

假设现在有这么一个需求,系统接了很多的报文,需要提供全文检索,为了简化,报文目前只有类型,流水号,内容这三个字段。

索引设计

建立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

标签:实战,msgSearchVO,keyword,报文,private,Elasticsearch,new,type
来源: https://www.cnblogs.com/wt20/p/16610987.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有