当前位置: 首页>后端>正文

js data索引 date索引

前言

对于索引结构一旦创建 就不能增加分片 除非重建索引

那对于这种需求我们该怎么办呢?

步骤

  1. blog取⼀个别名blog_latest, blog_latest作为对外使⽤
  2. 新增⼀个索引blog_20220101,结构复制于nba索引,根据业务要求修改字段
  3. 将blog数据同步到blog_20220101
  4. 给blog_20220101添加别名blog_latest,删除blog别名blog_latest
  5. 删除blog索引

我们对外提供访问blog索引时使⽤的是blog_latest别名

下面举两个例子来说明

准备工程代码

<?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>
    <groupId>com.haoran</groupId>
    <artifactId>blog-es</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>blog-es</name>
    <description>demo project for spring boot</description>

    <properties>
        <java.version>1.8</java.version>
        <!--		<elasticsearch.version>8.0.1</elasticsearch.version>-->
        <!--		<elasticsearch.version>7.17.2</elasticsearch.version>-->
    </properties>


    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.24</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
<!--            <exclusions>-->
<!--                <exclusion>-->
<!--                    <groupId>org.elasticsearch.client</groupId>-->
<!--                    <artifactId>elasticsearch-rest-high-level-client</artifactId>-->
<!--                </exclusion>-->
<!--            </exclusions>-->
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>

    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.7.1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

blog系统

假如我们有个blog系统 里面有 美食类  技术类  新闻类  历史类等等类型

我们可以这么设计一个索引映射如下:

主键  标题  类型 作者  发布日期 内容等字段

js data索引 date索引,js data索引 date索引_js data索引,第1张

package com.sixkery.entity.es;

import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.TypeAlias;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;

@Data
@TypeAlias("Blog")
@Document(indexName = "Blog")
public class AbstractBlog {

    @Id
    @Field(type = FieldType.Long)
    private Long id;

    @Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_max_word")
    private String title;

    @Field(type = FieldType.Keyword)
    private String type;

    @Field(type = FieldType.Keyword)
    private String author;

    @Field(type = FieldType.Date, pattern = "epoch_millis || yyyy-MM-dd HH:mm:ss")
    private Long publishDate;

    @Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_max_word")
    private String content;
}

美食类blog对象

@Data
@Document(indexName = "index_food_blog")
@Accessors
public class FoodBlog extends AbstractBlog {


}

技术类bolg对象

package com.sixkery.entity.es;

import lombok.Data;
import org.springframework.data.elasticsearch.annotations.Document;

@Data
@Document(indexName = "index_technology_blog")
public class TechnologyBlog extends AbstractBlog {


}

对应的mapping如下:

{
	"index_food_blog": {
		"aliases": {
			"Blog": {}
		},
		"mappings": {
			"properties": {
				"_class": {
					"type": "text",
					"fields": {
						"keyword": {
							"type": "keyword",
							"ignore_above": 256
						}
					}
				},
				"author": {
					"type": "keyword"
				},
				"content": {
					"type": "text",
					"analyzer": "ik_max_word"
				},
				"id": {
					"type": "keyword"
				},
				"publishDate": {
					"type": "date",
					"format": "epoch_millis || yyyy-MM-dd HH:mm:ss"
				},
				"title": {
					"type": "text",
					"analyzer": "ik_max_word"
				},
				"type": {
					"type": "keyword"
				}
			}
		},
		"settings": {
			"index": {
				"refresh_interval": "1s",
				"number_of_shards": "5",
				"provided_name": "index_food_blog",
				"creation_date": "1654742590809",
				"store": {
					"type": "fs"
				},
				"number_of_replicas": "1",
				"uuid": "HA1i6JWgSfyz04aaZcI48Q",
				"version": {
					"created": "7040299"
				}
			}
		}
	},
	"index_technology_blog": {
		"aliases": {
			"Blog": {}
		},
		"mappings": {
			"properties": {
				"_class": {
					"type": "text",
					"fields": {
						"keyword": {
							"type": "keyword",
							"ignore_above": 256
						}
					}
				},
				"author": {
					"type": "keyword"
				},
				"content": {
					"type": "text",
					"analyzer": "ik_max_word"
				},
				"id": {
					"type": "keyword"
				},
				"publishDate": {
					"type": "date",
					"format": "epoch_millis || yyyy-MM-dd HH:mm:ss"
				},
				"title": {
					"type": "text",
					"analyzer": "ik_max_word"
				},
				"type": {
					"type": "keyword"
				}
			}
		},
		"settings": {
			"index": {
				"refresh_interval": "1s",
				"number_of_shards": "5",
				"provided_name": "index_technology_blog",
				"creation_date": "1654742591150",
				"store": {
					"type": "fs"
				},
				"number_of_replicas": "1",
				"uuid": "gp1G1m7dRFCCflBJq3SA8g",
				"version": {
					"created": "7040299"
				}
			}
		}
	}
}

 看我们的查询和编辑操作

package com.sixkery.controller;


import com.sixkery.entity.es.AbstractBlog;
import com.sixkery.entity.es.FoodBlog;
import com.sixkery.entity.es.TechnologyBlog;
import com.sixkery.repository.*;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import org.elasticsearch.index.query.BoolQueryBuilder;
import org.springframework.beans.BeanUtils;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;

import org.springframework.data.elasticsearch.core.IndexOperations;
import org.springframework.data.elasticsearch.core.MultiGetItem;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.Query;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;

@RestController
@Slf4j
@RequestMapping("/blog")
public class BlogController {

    @Resource
    private ElasticsearchRestTemplate elasticsearchRestTemplate;
    @Resource
    private FoodBlogRepository foodBlogRepository;
    @Resource
    private TechnologyBlogRepository technologyBlogRepository;

    private AtomicLong id = new AtomicLong(0);

    @PostMapping("/add")
    public ResponseEntity<Object> addFoodBlog(@RequestBody BlogDTO blogDTO) {

        if (blogDTO.getType().equalsIgnoreCase("food")) {
            FoodBlog target = new FoodBlog();
            BeanUtils.copyProperties(blogDTO, target);
            target.setId(id.addAndGet(1));
            return ResponseEntity.ok(foodBlogRepository.save(target));
        } else {
            TechnologyBlog target = new TechnologyBlog();
            BeanUtils.copyProperties(blogDTO, target);
            target.setId(id.addAndGet(1));
            return ResponseEntity.ok(technologyBlogRepository.save(target));
        }
    }

    @GetMapping("/foodBlogs")
    public ResponseEntity<Iterable<FoodBlog>> foodBlogs() {
        return ResponseEntity.ok(foodBlogRepository.findAll());
    }

    @GetMapping("/technologyBlog")
    public ResponseEntity<Iterable<TechnologyBlog>> technologyBlog() {
        return ResponseEntity.ok(technologyBlogRepository.findAll());
    }

    @GetMapping("/allTypeBlog")
    public ResponseEntity<SearchHits<AbstractBlog>> allTypeBlog() {
//        elasticsearchRestTemplate.indexOps(FoodBlog.class).

        IndexCoordinates blog = IndexCoordinates.of("Blog");
//        IndexOperations indexOperations = elasticsearchRestTemplate.indexOps(blog);
        Query query = elasticsearchRestTemplate.matchAllQuery();
        SearchHits<AbstractBlog> search = elasticsearchRestTemplate.search(query, AbstractBlog.class, blog);
//        List<MultiGetItem<AbstractBlog>> multiGetItems = elasticsearchRestTemplate.multiGet(query, AbstractBlog.class);


        return ResponseEntity.ok(search);
    }

//    @DeleteMapping("/deleteIndex")
//    public ResponseEntity<Boolean> deleteIndex() {
//        boolean deleteIndex1 = elasticsearchRestTemplate.deleteIndex(FoodBlog.class);
//        boolean deleteIndex2 = elasticsearchRestTemplate.deleteIndex(TechnologyBlog.class);
//        return ResponseEntity.ok(deleteIndex1 && deleteIndex2);
//    }


//    @PutMapping("/createIndex")
//    public ResponseEntity<String> createIndex() {
//        boolean deleteIndex1 = elasticsearchRestTemplate.createIndex(FoodBlog.class);
//        boolean deleteIndex2 = elasticsearchRestTemplate.createIndex(TechnologyBlog.class);
//        boolean putMapping1 = elasticsearchRestTemplate.putMapping(FoodBlog.class);
//        boolean putMapping2 = elasticsearchRestTemplate.putMapping(TechnologyBlog.class);
//        boolean addAlias1 = ElasticsearchIndexOps.addAlias(FoodBlog.class.getAnnotation(Document.class).indexName(),
//                FoodBlog.class.getAnnotation(TypeAlias.class).value());
//        boolean addAlias2 = ElasticsearchIndexOps.addAlias(TechnologyBlog.class.getAnnotation(Document.class).indexName(),
//                TechnologyBlog.class.getAnnotation(TypeAlias.class).value());
//        return ResponseEntity.ok(String.join("  ", Boolean.toString(deleteIndex1), Boolean.toString(deleteIndex2),
//                Boolean.toString(putMapping1), Boolean.toString(putMapping2), Boolean.toString(addAlias1), Boolean.toString(addAlias2)));
//    }


//    @PutMapping("/indexAlias")
//    public ResponseEntity<Map<String, Set<String>>> indexAlias() {
//        Map<String, Set<String>> map = new HashMap<>();
//        String index1 = FoodBlog.class.getAnnotation(Document.class).indexName();
//        Set<String> alias1 = ElasticsearchIndexOps.getAlias(index1);
//        map.put(index1, alias1);
//        String index2 = FoodBlog.class.getAnnotation(Document.class).indexName();
//        Set<String> alias2 = ElasticsearchIndexOps.getAlias(index2);
//        map.put(index2, alias2);
//        return ResponseEntity.ok(map);
//    }
//
//    @PutMapping("/deleteAlias")
//    public ResponseEntity<Map<String, Set<String>>> deleteAlias() {
//        Map<String, Set<String>> map = new HashMap<>();
//        String index1 = FoodBlog.class.getAnnotation(Document.class).indexName();
//        Set<String> alias1 = ElasticsearchIndexOps.getAlias(index1);
//        ElasticsearchIndexOps.delAlias(index1, alias1.toArray(new String[]{}));
//        String index2 = FoodBlog.class.getAnnotation(Document.class).indexName();
//        Set<String> alias2 = ElasticsearchIndexOps.getAlias(index2);
//        ElasticsearchIndexOps.delAlias(index2, alias2.toArray(new String[]{}));
//        return ResponseEntity.ok(map);
//    }
}

@Data
class BlogDTO extends AbstractBlog {

}

2 大数据

js data索引 date索引,js data索引 date索引_elasticsearch_02,第2张

项目实战

订单记录 增加字段的一次 迭代升级

v0  版本  createTime  ....

 需要增加一个支付时间 

v1  版本  createTime  ....  paymentTime

package com.sixkery.entity.es;


import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonView;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.TypeAlias;
import org.springframework.data.elasticsearch.annotations.*;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

/**
 * @Field(type=FieldType.Text, analyzer=“ik_max_word”) 表示该字段是一个文本,并作最大程度拆分,默认建立索引
 * @Field(type=FieldType.Text,index=false) 表示该字段是一个文本,不建立索引
 * @Field(type=FieldType.Date) 表示该字段是一个文本,日期类型,默认不建立索引
 * @Field(type=FieldType.Long) 表示该字段是一个长整型,默认建立索引
 * @Field(type=FieldType.Keyword) 表示该字段内容是一个文本并作为一个整体不可分,默认建立索引
 * @Field(type=FieldType.Float) 表示该字段内容是一个浮点类型并作为一个整体不可分,默认建立索引
 * <p>
 * date 、float、long都是不能够被拆分的
 */
@Data
@Document(indexName = "charge_detail_record", createIndex = false)
@TypeAlias("charge_detail_record_latest")
@Setting(settingPath = "elastic/setting/ChargeDetailRecordBill.json")
public class ChargeDetailRecord {

    /**
     * <p>订单明细</p>
     * 订单号
     * 站点名称
     * 桩名称
     * 枪号
     * 成员名称
     * 子成员名称
     * 充电时长
     * 停止原因
     * 桩序列号
     * 手机号
     * 开始时间
     * 结束时间
     * 总电量
     * 总起始值
     * 总止示值
     * 开始SOC
     * 结束SOC
     * 实收电费
     * 账单金额
     * 实收金额
     * 折扣金额
     * 卡号
     * 支付状态
     * 备注
     */
    public interface OrderView {

    }

    public interface OrderDetail extends OrderView {

    }

    public interface InvoiceBill {

    }


    /**
     * 交易明细
     * 字段
     * <p>
     * 订单号
     * 站点名称
     * 桩名称
     * 桩序列号
     * 用户名称
     * 业务类型
     * 业务类型
     * 充电量(度)
     * 充电时长
     * 实收金额
     * 支付状态
     * 支付方式
     * 支付流水号
     * 充电开始时间
     * 充电结束时间
     */
    public interface TradeView {

    }

    /*↓↓↓↓↓↓↓↓↓↓↓↓CDR表信息↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓*/


    /**
     * 账单ID   tb_cdr 主键
     */
    @Id
    @Field(type = FieldType.Long)
    @JsonView({TradeView.class, OrderView.class})
    @JsonFormat(shape = JsonFormat.Shape.STRING)
    private Long id;

    /**
     * Uniquely identifies the CDR within the CPOs platform
     */
    @Field(type = FieldType.Keyword, normalizer = "lowercase")
    @JsonView({TradeView.class})
    private String uid;

    /**
     * start timestamp of the charging session.
     */
    @Field(type = FieldType.Date, format = DateFormat.epoch_millis, pattern = "epoch_millis")
    @JsonView({TradeView.class, OrderView.class, InvoiceBill.class})
    private LocalDate startDateTime;

    /**
     * stop timestamp of the charging session.
     */
    @Field(type = FieldType.Date, format = DateFormat.epoch_millis, pattern = "epoch_millis")
    @JsonView({TradeView.class, OrderView.class, InvoiceBill.class})

    private LocalDate stopDateTime;

    /**
     * reference to a token, identified by the auth_id field
     */
    @Field(type = FieldType.Keyword, normalizer = "lowercase")

    private String authId;

    /**
     * auth_request,whitelist
     */
    @Field(type = FieldType.Keyword, normalizer = "lowercase")

    private String authMethod;

    /**
     * identification of the meter inside the charge point.
     */
    @Field(type = FieldType.Keyword, normalizer = "lowercase")

    private String meterId;

    /**
     * currency of the cdr in iso 4217 code.
     */
    @Field(type = FieldType.Keyword, normalizer = "lowercase")

    @JsonView({TradeView.class, OrderDetail.class, InvoiceBill.class})
    private String currency;

    /**
     * Currency 符号
     */
    @Field(type = FieldType.Keyword)

    @JsonView({TradeView.class, OrderView.class, OrderDetail.class, InvoiceBill.class})
    private String currencySymbol;

    /**
     * total cost (excluding vat)
     */
    @Field(type = FieldType.Double)

    @JsonView({InvoiceBill.class})

    private BigDecimal totalCost;

    /**
     * 充电量(度)
     * total energy charged, in kwh.
     */
    @Field(type = FieldType.Double)
    @JsonView({TradeView.class, OrderView.class, InvoiceBill.class})


    private BigDecimal totalEnergy;

    /**
     * total duration of this session (including the duration
     */
    @Field(type = FieldType.Double)

    private BigDecimal totalTime;

    /**
     * total duration during this session that the ev is not
     */
    @Field(type = FieldType.Double)

    private BigDecimal totalParkingTime;

    /**
     * optional remark, can be used to provide addition
     * 备注
     */
    @Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_max_word")
    @JsonView({OrderView.class})

    private String remark;

    @Field(type = FieldType.Text, index = false)
    @JsonView({OrderView.class})

    private String chargingPeriods;


    @Field(type = FieldType.Text, index = false)
    private String tariffs;

    /**
     * cdr最后更新时间
     */

    @Field(type = FieldType.Date, format = DateFormat.epoch_millis, pattern = "epoch_millis")
    private LocalDate lastUpdated;

    /*↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑CDR 表信息↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑*/


    /*↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓充电账单信息↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓****/

    /**
     * 账单ID   tb_bill 主键
     */
    @Field(type = FieldType.Long)
    @JsonView({TradeView.class, OrderView.class, InvoiceBill.class})

    @JsonFormat(shape = JsonFormat.Shape.STRING)
    private Long billId;
    /**
     * 收到桩侧开始充电回调信息的时间
     */

    @Field(type = FieldType.Date, format = DateFormat.epoch_millis, pattern = "epoch_millis")
    private LocalDate startCallbackTime;

    /**
     * 收到桩侧结束充电回调信息的时间
     */

    @Field(type = FieldType.Date, format = DateFormat.epoch_millis, pattern = "epoch_millis")
    private LocalDate stopCallbackTime;
    /**
     * 订单流水号  与桩交互使用
     */
    @Field(type = FieldType.Keyword, normalizer = "lowercase")
    @JsonView({TradeView.class, OrderDetail.class, OrderView.class})

    private String orderSeq;

    /**
     * op_location_evse 主键
     */
    @Field(type = FieldType.Long)

    @JsonFormat(shape = JsonFormat.Shape.STRING)
    private Long evseId;

    /**
     * 场站ID   locationId 主键
     */
    @Field(type = FieldType.Long)
    @JsonView({TradeView.class, OrderView.class})

    @JsonFormat(shape = JsonFormat.Shape.STRING)
    private Long locationId;

    /**
     * 客户(member)
     */
    @Field(type = FieldType.Long)

    @JsonFormat(shape = JsonFormat.Shape.STRING)
    private Long memberId;


    /**
     * 客户(openid)
     */
    @Field(type = FieldType.Keyword)
    @JsonView({OrderView.class, TradeView.class, InvoiceBill.class})

    @JsonFormat(shape = JsonFormat.Shape.STRING)
    private Long userId;

    /**
     * 商家id
     */
    @Field(type = FieldType.Long)

    @JsonFormat(shape = JsonFormat.Shape.STRING)
    private Long operatorId;

    /**
     * 卡号
     */
    @Field(type = FieldType.Keyword, normalizer = "lowercase")
    @JsonView({OrderView.class, TradeView.class})

    private String cardNo;


    /**
     * 订单状态 -1: 启动失败, 0:DEFAULT,  1:启动成功,  2、订单结束 3、异常订单
     */
    @Field(type = FieldType.Integer)
    @JsonView({OrderView.class, TradeView.class})

    private Integer orderStatus;


    /**
     * 订单类型   0:正常订单,  1、异常订单
     */
    @Field(type = FieldType.Integer)
    @JsonView({OrderView.class, TradeView.class})

    private Integer orderType;

    /**
     * 订单异常原因
     */
    @Field(type = FieldType.Text)
    @JsonView({OrderView.class, TradeView.class})

    private String errorCause;


    /**
     * 充电设备Sn码
     */
    @Field(type = FieldType.Keyword, normalizer = "lowercase")
    @JsonView({TradeView.class, OrderView.class})
    private String evseSn;


    /**
     * 订单号
     * 订单编码
     * 订单编号
     * uniquely identifies the cdr within the cpos platform
     */
    @Field(type = FieldType.Keyword, normalizer = "lowercase")
    @JsonView({TradeView.class, OrderView.class, InvoiceBill.class})
    private String orderNumber;

    /**
     * 支付方式 1 Stripe; 2 Paypal; 3 Google; 4 Apple; 5 POS机
     */
    @Field(type = FieldType.Integer)

    @JsonView({TradeView.class, InvoiceBill.class})
    private Integer payType;


    /**
     * 支付状态 0.default 1.待支付, 2.已支付,3.免支付
     */
    @Field(type = FieldType.Integer)
    @JsonView({TradeView.class, OrderView.class, InvoiceBill.class})

    private Integer payStatus;

    /**
     * 支付流水号
     */
    @Field(type = FieldType.Keyword, normalizer = "lowercase")
    @JsonView({TradeView.class})

    private String paySeq;

    /**
     * POS机流水号
     */
    @Field(type = FieldType.Keyword, normalizer = "lowercase")
    @JsonView({TradeView.class})

    private String posSeq;

    /**
     * 充电模式(充电策略)
     * 充电模式(充电策略) 1,"自动模式" 2,"金额模式" , 3,"时间模式" 4,"电量模式"
     */
    @Field(type = FieldType.Integer)
    @JsonView({OrderView.class, TradeView.class})

    private Integer chargingMode;


    /**
     * 1:刷卡,2:扫码,3:即插即充,4:POS, 5:OCPI START SESSION , 6:OCPI SWIPE RFID
     * 原来的BusType
     */
    @Field(type = FieldType.Integer)
    @JsonView({OrderView.class, TradeView.class})

    private Integer chargingType;


    @Field(type = FieldType.Integer)
    @JsonView({OrderView.class, TradeView.class})

    private Integer businessType;

    /**
     * 停止原因
     */
    @Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_max_word")
    @JsonView({OrderView.class})

    private String stopReason;

    /**
     * 充电时长毫秒
     */
    @Field(type = FieldType.Long)

    @JsonView({TradeView.class, OrderView.class, OrderView.class})
    private Long duration;

    /**
     * 开始soc
     */
    @Field(type = FieldType.Double)
    @JsonView({OrderDetail.class, OrderView.class})

    private BigDecimal startSoc;

    /**
     * 结束soc
     */
    @Field(type = FieldType.Double)
    @JsonView({OrderDetail.class, OrderView.class})

    private BigDecimal stopSoc;

    /**
     * 总起示值
     * 总起始值
     * wh
     */
    @Field(type = FieldType.Long)
    @JsonView({OrderDetail.class, TradeView.class, OrderView.class})

    private Long startMeterValue;

    /**
     * 总止示值
     * wh
     */
    @Field(type = FieldType.Long)
    @JsonView({OrderDetail.class, TradeView.class, OrderView.class})

    private Long stopMeterValue;

    /**
     * 总电费(元)
     */
    @Field(type = FieldType.Double)
    @JsonView({OrderDetail.class, OrderView.class})

    private BigDecimal totalEnergyFee;

    /**
     * 总电量(Wh)
     */
    @Field(type = FieldType.Long)
    @JsonView({OrderDetail.class, OrderView.class})

    private Long sumPower;

    /**
     * 实际总电费(元)
     */
    @Field(type = FieldType.Double)
    @JsonView({TradeView.class, OrderView.class})

    private BigDecimal actualTotalEnergyFee;


    /**
     * 时长费(元)
     */
    @Field(type = FieldType.Double)
    @JsonView({OrderDetail.class})


    private BigDecimal timeFee;


    /**
     * 启动费(元)
     */
    @Field(type = FieldType.Double)
    @JsonView({OrderDetail.class})
    private BigDecimal startFee;


    /**
     * 账单金额(消费金额)
     * 账单金额
     */
    @Field(type = FieldType.Double)
    @JsonView({OrderDetail.class, OrderView.class})
    private BigDecimal totalAmount;

    @Field(type = FieldType.Double, index = false)
    @JsonView({OrderDetail.class, OrderView.class})
    private BigDecimal discount;

    /**
     * 折扣金额
     */
    @Field(type = FieldType.Double)
    @JsonView({OrderDetail.class, OrderView.class})
    private BigDecimal discountAmount;

    /**
     * 免收金额
     * freeAmount(免收金额) = totalAmount (账单金额) - paymentAmount(支付金额)
     */
    @Field(type = FieldType.Double)
    @JsonView({OrderDetail.class, OrderView.class})
    private BigDecimal freeAmount;

    /**
     * 退款金额
     * refundAmount
     */
    @Field(type = FieldType.Double)
    @JsonView({OrderDetail.class, OrderView.class})
    private BigDecimal refundAmount;

    /**
     * 实收金额
     */
    @Field(type = FieldType.Double)
    @JsonView({TradeView.class, OrderView.class, InvoiceBill.class})
    private BigDecimal paymentAmount;

    @Field(type = FieldType.Boolean)
    @JsonView({TradeView.class})

    private Boolean invoiced;

    /**
     * 站点时区
     */
    @Field(type = FieldType.Keyword, normalizer = "lowercase")
    @JsonView({TradeView.class, OrderView.class})

    private String timeZone;


    /**
     * 支付失败原因
     */
    @Field(type = FieldType.Keyword, normalizer = "lowercase")
    @JsonView(TradeView.class)

    private String payFailReason;


    @Field(type = FieldType.Integer)
    private Integer evseType;

    /**
     * 创建人
     */
    @Field(type = FieldType.Long)
    @JsonFormat(shape = JsonFormat.Shape.STRING)
    private Long createBy;

    /**
     * 创建时间
     */
    @Field(type = FieldType.Date, format = DateFormat.epoch_millis, pattern = "epoch_millis")
    private LocalDate createTime;

    /**
     * 更新人
     */
    @Field(type = FieldType.Long)
    @JsonFormat(shape = JsonFormat.Shape.STRING)
    private Long updateBy;

    /**
     * 更新时间
     */
    @Field(type = FieldType.Date, format = DateFormat.epoch_millis, pattern = "epoch_millis")
    private LocalDate updateTime;

    /*↑↑↑↑↑↑↑↑↑↑↑↑上面信息来自账单表↑↑↑↑↑↑↑↑↑↑↑↑↑*/

    /*↓↓↓↓↓↓↓↓↓↓冗余字段↓↓↓↓↓↓↓↓↓↓↓*/

    /**
     * 手机号码
     * 用户手机号
     */
    @Field(type = FieldType.Keyword, normalizer = "lowercase")
    @JsonView({TradeView.class, OrderView.class, OrderDetail.class})

    private String telephone;

    /**
     * 用户邮箱
     */
    @Field(type = FieldType.Keyword, normalizer = "lowercase")
    @JsonView({TradeView.class, OrderView.class, InvoiceBill.class})

    private String email;

    /**
     * 充电用户名称
     * 成员名称
     */
    @Field(type = FieldType.Keyword, normalizer = "lowercase")
    @JsonView({TradeView.class, OrderView.class, InvoiceBill.class})

    private String memberName;

    /**
     * 站点名称
     */
    @Field(type = FieldType.Keyword, normalizer = "lowercase")
    @JsonView({TradeView.class, OrderView.class, InvoiceBill.class})

    private String locationName;

    /**
     * 桩名称
     */
    @Field(type = FieldType.Keyword, normalizer = "lowercase")
    @JsonView({TradeView.class, OrderView.class})

    private String pileName;

    @Field(type = FieldType.Keyword, normalizer = "lowercase")
    @JsonView({TradeView.class, OrderView.class})

    private String gunNo;

    /**
     * 桩序列号
     */
    @Field(type = FieldType.Keyword, normalizer = "lowercase")
    @JsonView({TradeView.class, OrderView.class, OrderDetail.class})
    private String pileSn;


    @Field(type = FieldType.Integer)

    private Integer year;

    @Field(type = FieldType.Integer)

    private Integer month;

    @Field(type = FieldType.Integer)

    private Integer quarter;

    @Field(type = FieldType.Text)

    private String pileAddress;

    @Field(type = FieldType.Boolean)

    private Boolean ocpiEnabled = false;

    /**
     * 充电中的监控
     */
    @JsonView({OrderDetail.class})
    @Field(type = FieldType.Object, index = false)
    private List<Measure> measures = new ArrayList<>();

    /*↑↑↑↑↑↑↑↑↑↑↑↑冗余字段↑↑↑↑↑↑↑↑↑↑↑↑↑*/

}

分词器索引

{

    "index": {
      "max_ngram_diff": "30",
      "refresh_interval": "1s",
      "number_of_shards": "3",
      "store": {
        "type": "fs"
      },
      "analysis": {
        "normalizer": {
          "lowercase": {
            "filter": [
              "lowercase"
            ],
            "type": "custom"
          }
        },
        "analyzer": {
          "index_analyzer": {
            "filter": [
              "lowercase"
            ],
            "tokenizer": "my_tokenizer"
          },
          "search_analyzer": {
            "filter": [
              "lowercase"
            ],
            "tokenizer": "whitespace"
          }
        },
        "tokenizer": {
          "my_tokenizer": {
            "token_chars": [
              "letter",
              "digit",
              "punctuation",
              "symbol"
            ],
            "min_gram": "1",
            "type": "ngram",
            "max_gram": "30"
          }
        }
      },
      "number_of_replicas": "1"
    }

}

v1

package com.sixkery.entity.es;


import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonView;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.TypeAlias;
import org.springframework.data.elasticsearch.annotations.*;

import java.math.BigDecimal;
import java.util.Date;
import java.util.ArrayList;
import java.util.List;

/**
 * @Field(type=FieldType.Text, analyzer=“ik_max_word”) 表示该字段是一个文本,并作最大程度拆分,默认建立索引
 * @Field(type=FieldType.Text,index=false) 表示该字段是一个文本,不建立索引
 * @Field(type=FieldType.Date) 表示该字段是一个文本,日期类型,默认不建立索引
 * @Field(type=FieldType.Long) 表示该字段是一个长整型,默认建立索引
 * @Field(type=FieldType.Keyword) 表示该字段内容是一个文本并作为一个整体不可分,默认建立索引
 * @Field(type=FieldType.Float) 表示该字段内容是一个浮点类型并作为一个整体不可分,默认建立索引
 * <p>
 * date 、float、long都是不能够被拆分的
 */
@Data
@Document(indexName = "charge_detail_record_v1")
@TypeAlias("charge_detail_record_latest")
@Setting(settingPath = "elastic/setting/ChargeDetailRecordBill.json")
public class ChargeDetailRecord_V1 {

    /**
     * <p>订单明细</p>
     * 订单号
     * 站点名称
     * 桩名称
     * 枪号
     * 成员名称
     * 子成员名称
     * 充电时长
     * 停止原因
     * 桩序列号
     * 手机号
     * 开始时间
     * 结束时间
     * 总电量
     * 总起始值
     * 总止示值
     * 开始SOC
     * 结束SOC
     * 实收电费
     * 账单金额
     * 实收金额
     * 折扣金额
     * 卡号
     * 支付状态
     * 备注
     */
    public interface OrderView {

    }

    public interface OrderDetail extends OrderView {

    }

    public interface InvoiceBill {

    }


    /**
     * 交易明细
     * 字段
     * <p>
     * 订单号
     * 站点名称
     * 桩名称
     * 桩序列号
     * 用户名称
     * 业务类型
     * 业务类型
     * 充电量(度)
     * 充电时长
     * 实收金额
     * 支付状态
     * 支付方式
     * 支付流水号
     * 充电开始时间
     * 充电结束时间
     */
    public interface TradeView {

    }

    /*↓↓↓↓↓↓↓↓↓↓↓↓CDR表信息↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓*/


    /**
     * 账单ID   tb_cdr 主键
     */
    @Id
    @Field(type = FieldType.Long)
    @JsonView({TradeView.class, OrderView.class})
    @JsonFormat(shape = JsonFormat.Shape.STRING)
    private Long id;

    /**
     * Uniquely identifies the CDR within the CPOs platform
     */
    @Field(type = FieldType.Keyword, normalizer = "lowercase")
    @JsonView({TradeView.class})
    private String uid;

    /**
     * start timestamp of the charging session.
     */
    @Field(type = FieldType.Date, format = DateFormat.epoch_millis, pattern = "epoch_millis")
    @JsonView({TradeView.class, OrderView.class, InvoiceBill.class})
    private Date startDateTime;

    /**
     * stop timestamp of the charging session.
     */
    @Field(type = FieldType.Date, format = DateFormat.epoch_millis, pattern = "epoch_millis")
    @JsonView({TradeView.class, OrderView.class, InvoiceBill.class})

    private Date stopDateTime;

    /**
     * reference to a token, identified by the auth_id field
     */
    @Field(type = FieldType.Keyword, normalizer = "lowercase")

    private String authId;

    /**
     * auth_request,whitelist
     */
    @Field(type = FieldType.Keyword, normalizer = "lowercase")

    private String authMethod;

    /**
     * identification of the meter inside the charge point.
     */
    @Field(type = FieldType.Keyword, normalizer = "lowercase")

    private String meterId;

    /**
     * currency of the cdr in iso 4217 code.
     */
    @Field(type = FieldType.Keyword, normalizer = "lowercase")

    @JsonView({TradeView.class, OrderDetail.class, InvoiceBill.class})
    private String currency;

    /**
     * Currency 符号
     */
    @Field(type = FieldType.Keyword)

    @JsonView({TradeView.class, OrderView.class, OrderDetail.class, InvoiceBill.class})
    private String currencySymbol;

    /**
     * total cost (excluding vat)
     */
    @Field(type = FieldType.Double)

    @JsonView({InvoiceBill.class})

    private BigDecimal totalCost;

    /**
     * 充电量(度)
     * total energy charged, in kwh.
     */
    @Field(type = FieldType.Double)
    @JsonView({TradeView.class, OrderView.class, InvoiceBill.class})


    private BigDecimal totalEnergy;

    /**
     * total duration of this session (including the duration
     */
    @Field(type = FieldType.Double)

    private BigDecimal totalTime;

    /**
     * total duration during this session that the ev is not
     */
    @Field(type = FieldType.Double)

    private BigDecimal totalParkingTime;

    /**
     * optional remark, can be used to provide addition
     * 备注
     */
    @Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_max_word")
    @JsonView({OrderView.class})

    private String remark;

    @Field(type = FieldType.Text, index = false)
    @JsonView({OrderView.class})

    private String chargingPeriods;


    @Field(type = FieldType.Text, index = false)
    private String tariffs;

    /**
     * cdr最后更新时间
     */

    @Field(type = FieldType.Date, format = DateFormat.epoch_millis, pattern = "epoch_millis")
    private Date lastUpdated;

    /*↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑CDR 表信息↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑*/


    /*↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓充电账单信息↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓****/

    /**
     * 账单ID   tb_bill 主键
     */
    @Field(type = FieldType.Long)
    @JsonView({TradeView.class, OrderView.class, InvoiceBill.class})

    @JsonFormat(shape = JsonFormat.Shape.STRING)
    private Long billId;
    /**
     * 收到桩侧开始充电回调信息的时间
     */

    @Field(type = FieldType.Date, format = DateFormat.epoch_millis, pattern = "epoch_millis")
    private Date startCallbackTime;

    /**
     * 收到桩侧结束充电回调信息的时间
     */

    @Field(type = FieldType.Date, format = DateFormat.epoch_millis, pattern = "epoch_millis")
    private Date stopCallbackTime;
    /**
     * 订单流水号  与桩交互使用
     */
    @Field(type = FieldType.Keyword, normalizer = "lowercase")
    @JsonView({TradeView.class, OrderDetail.class, OrderView.class})

    private String orderSeq;

    /**
     * op_location_evse 主键
     */
    @Field(type = FieldType.Long)

    @JsonFormat(shape = JsonFormat.Shape.STRING)
    private Long evseId;

    /**
     * 场站ID   locationId 主键
     */
    @Field(type = FieldType.Long)
    @JsonView({TradeView.class, OrderView.class})

    @JsonFormat(shape = JsonFormat.Shape.STRING)
    private Long locationId;

    /**
     * 客户(member)
     */
    @Field(type = FieldType.Long)

    @JsonFormat(shape = JsonFormat.Shape.STRING)
    private Long memberId;


    /**
     * 客户(openid)
     */
    @Field(type = FieldType.Keyword)
    @JsonView({OrderView.class, TradeView.class, InvoiceBill.class})

    @JsonFormat(shape = JsonFormat.Shape.STRING)
    private Long userId;

    /**
     * 商家id
     */
    @Field(type = FieldType.Long)

    @JsonFormat(shape = JsonFormat.Shape.STRING)
    private Long operatorId;

    /**
     * 卡号
     */
    @Field(type = FieldType.Keyword, normalizer = "lowercase")
    @JsonView({OrderView.class, TradeView.class})

    private String cardNo;


    /**
     * 订单状态 -1: 启动失败, 0:DEFAULT,  1:启动成功,  2、订单结束 3、异常订单
     */
    @Field(type = FieldType.Integer)
    @JsonView({OrderView.class, TradeView.class})

    private Integer orderStatus;


    /**
     * 订单类型   0:正常订单,  1、异常订单
     */
    @Field(type = FieldType.Integer)
    @JsonView({OrderView.class, TradeView.class})

    private Integer orderType;

    /**
     * 订单异常原因
     */
    @Field(type = FieldType.Text)
    @JsonView({OrderView.class, TradeView.class})

    private String errorCause;


    /**
     * 充电设备Sn码
     */
    @Field(type = FieldType.Keyword, normalizer = "lowercase")
    @JsonView({TradeView.class, OrderView.class})
    private String evseSn;


    /**
     * 订单号
     * 订单编码
     * 订单编号
     * uniquely identifies the cdr within the cpos platform
     */
    @Field(type = FieldType.Keyword, normalizer = "lowercase")
    @JsonView({TradeView.class, OrderView.class, InvoiceBill.class})
    private String orderNumber;

    /**
     * 支付方式 1 Stripe; 2 Paypal; 3 Google; 4 Apple; 5 POS机
     */
    @Field(type = FieldType.Integer)

    @JsonView({TradeView.class, InvoiceBill.class})
    private Integer payType;


    /**
     * 支付状态 0.default 1.待支付, 2.已支付,3.免支付
     */
    @Field(type = FieldType.Integer)
    @JsonView({TradeView.class, OrderView.class, InvoiceBill.class})

    private Integer payStatus;

    @Field(type = FieldType.Date, format = DateFormat.epoch_millis, pattern = "epoch_millis")
    @JsonView({TradeView.class, OrderView.class, InvoiceBill.class})
    private Date paymentTime;

    /**
     * 支付流水号
     */
    @Field(type = FieldType.Keyword, normalizer = "lowercase")
    @JsonView({TradeView.class})

    private String paySeq;

    /**
     * POS机流水号
     */
    @Field(type = FieldType.Keyword, normalizer = "lowercase")
    @JsonView({TradeView.class})

    private String posSeq;

    /**
     * 充电模式(充电策略)
     * 充电模式(充电策略) 1,"自动模式" 2,"金额模式" , 3,"时间模式" 4,"电量模式"
     */
    @Field(type = FieldType.Integer)
    @JsonView({OrderView.class, TradeView.class})

    private Integer chargingMode;


    /**
     * 1:刷卡,2:扫码,3:即插即充,4:POS, 5:OCPI START SESSION , 6:OCPI SWIPE RFID
     * 原来的BusType
     */
    @Field(type = FieldType.Integer)
    @JsonView({OrderView.class, TradeView.class})

    private Integer chargingType;


    @Field(type = FieldType.Integer)
    @JsonView({OrderView.class, TradeView.class})

    private Integer businessType;

    /**
     * 停止原因
     */
    @Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_max_word")
    @JsonView({OrderView.class})

    private String stopReason;

    /**
     * 充电时长毫秒
     */
    @Field(type = FieldType.Long)

    @JsonView({TradeView.class, OrderView.class, OrderView.class})
    private Long duration;

    /**
     * 开始soc
     */
    @Field(type = FieldType.Double)
    @JsonView({OrderDetail.class, OrderView.class})

    private BigDecimal startSoc;

    /**
     * 结束soc
     */
    @Field(type = FieldType.Double)
    @JsonView({OrderDetail.class, OrderView.class})

    private BigDecimal stopSoc;

    /**
     * 总起示值
     * 总起始值
     * wh
     */
    @Field(type = FieldType.Long)
    @JsonView({OrderDetail.class, TradeView.class, OrderView.class})

    private Long startMeterValue;

    /**
     * 总止示值
     * wh
     */
    @Field(type = FieldType.Long)
    @JsonView({OrderDetail.class, TradeView.class, OrderView.class})

    private Long stopMeterValue;

    /**
     * 总电费(元)
     */
    @Field(type = FieldType.Double)
    @JsonView({OrderDetail.class, OrderView.class})

    private BigDecimal totalEnergyFee;

    /**
     * 总电量(Wh)
     */
    @Field(type = FieldType.Long)
    @JsonView({OrderDetail.class, OrderView.class})

    private Long sumPower;

    /**
     * 实际总电费(元)
     */
    @Field(type = FieldType.Double)
    @JsonView({TradeView.class, OrderView.class})

    private BigDecimal actualTotalEnergyFee;


    /**
     * 时长费(元)
     */
    @Field(type = FieldType.Double)
    @JsonView({OrderDetail.class})


    private BigDecimal timeFee;


    /**
     * 启动费(元)
     */
    @Field(type = FieldType.Double)
    @JsonView({OrderDetail.class})
    private BigDecimal startFee;


    /**
     * 账单金额(消费金额)
     * 账单金额
     */
    @Field(type = FieldType.Double)
    @JsonView({OrderDetail.class, OrderView.class})
    private BigDecimal totalAmount;

    @Field(type = FieldType.Double, index = false)
    @JsonView({OrderDetail.class, OrderView.class})
    private BigDecimal discount;

    /**
     * 折扣金额
     */
    @Field(type = FieldType.Double)
    @JsonView({OrderDetail.class, OrderView.class})
    private BigDecimal discountAmount;

    /**
     * 免收金额
     * freeAmount(免收金额) = totalAmount (账单金额) - paymentAmount(支付金额)
     */
    @Field(type = FieldType.Double)
    @JsonView({OrderDetail.class, OrderView.class})
    private BigDecimal freeAmount;

    /**
     * 退款金额
     * refundAmount
     */
    @Field(type = FieldType.Double)
    @JsonView({OrderDetail.class, OrderView.class})
    private BigDecimal refundAmount;

    /**
     * 实收金额
     */
    @Field(type = FieldType.Double)
    @JsonView({TradeView.class, OrderView.class, InvoiceBill.class})
    private BigDecimal paymentAmount;

    @Field(type = FieldType.Boolean)
    @JsonView({TradeView.class})

    private Boolean invoiced;

    /**
     * 站点时区
     */
    @Field(type = FieldType.Keyword, normalizer = "lowercase")
    @JsonView({TradeView.class, OrderView.class})

    private String timeZone;


    /**
     * 支付失败原因
     */
    @Field(type = FieldType.Keyword, normalizer = "lowercase")
    @JsonView(TradeView.class)

    private String payFailReason;


    @Field(type = FieldType.Integer)
    private Integer evseType;

    /**
     * 创建人
     */
    @Field(type = FieldType.Long)
    @JsonFormat(shape = JsonFormat.Shape.STRING)
    private Long createBy;

    /**
     * 创建时间
     */
    @Field(type = FieldType.Date, format = DateFormat.epoch_millis, pattern = "epoch_millis")
    private Date createTime;

    /**
     * 更新人
     */
    @Field(type = FieldType.Long)
    @JsonFormat(shape = JsonFormat.Shape.STRING)
    private Long updateBy;

    /**
     * 更新时间
     */
    @Field(type = FieldType.Date, format = DateFormat.epoch_millis, pattern = "epoch_millis")
    private Date updateTime;

    /*↑↑↑↑↑↑↑↑↑↑↑↑上面信息来自账单表↑↑↑↑↑↑↑↑↑↑↑↑↑*/

    /*↓↓↓↓↓↓↓↓↓↓冗余字段↓↓↓↓↓↓↓↓↓↓↓*/

    /**
     * 手机号码
     * 用户手机号
     */
    @Field(type = FieldType.Keyword, normalizer = "lowercase")
    @JsonView({TradeView.class, OrderView.class, OrderDetail.class})

    private String telephone;

    /**
     * 用户邮箱
     */
    @Field(type = FieldType.Keyword, normalizer = "lowercase")
    @JsonView({TradeView.class, OrderView.class, InvoiceBill.class})

    private String email;

    /**
     * 充电用户名称
     * 成员名称
     */
    @Field(type = FieldType.Keyword, normalizer = "lowercase")
    @JsonView({TradeView.class, OrderView.class, InvoiceBill.class})

    private String memberName;

    /**
     * 站点名称
     */
    @Field(type = FieldType.Keyword, normalizer = "lowercase")
    @JsonView({TradeView.class, OrderView.class, InvoiceBill.class})

    private String locationName;

    /**
     * 桩名称
     */
    @Field(type = FieldType.Keyword, normalizer = "lowercase")
    @JsonView({TradeView.class, OrderView.class})

    private String pileName;

    @Field(type = FieldType.Keyword, normalizer = "lowercase")
    @JsonView({TradeView.class, OrderView.class})

    private String gunNo;

    /**
     * 桩序列号
     */
    @Field(type = FieldType.Keyword, normalizer = "lowercase")
    @JsonView({TradeView.class, OrderView.class, OrderDetail.class})
    private String pileSn;


    @Field(type = FieldType.Integer)

    private Integer year;

    @Field(type = FieldType.Integer)

    private Integer month;

    @Field(type = FieldType.Integer)

    private Integer quarter;

    @Field(type = FieldType.Text)

    private String pileAddress;

    @Field(type = FieldType.Boolean)

    private Boolean ocpiEnabled = false;

    /**
     * 充电中的监控
     */
    @JsonView({OrderDetail.class})
    @Field(type = FieldType.Object, index = false)
    private List<Measure> measures = new ArrayList<>();

    /*↑↑↑↑↑↑↑↑↑↑↑↑冗余字段↑↑↑↑↑↑↑↑↑↑↑↑↑*/

}
package com.sixkery.controller;

import com.sixkery.entity.es.*;
import org.springframework.data.annotation.TypeAlias;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.IndexOperations;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.index.AliasAction;
import org.springframework.data.elasticsearch.core.index.AliasActionParameters;
import org.springframework.data.elasticsearch.core.index.AliasActions;
import org.springframework.data.elasticsearch.core.index.AliasData;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.Query;
import org.springframework.data.elasticsearch.core.reindex.ReindexRequest;
import org.springframework.data.elasticsearch.core.reindex.ReindexResponse;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.Map;
import java.util.Set;

@RestController
public class ElasticsearchIndexOpsController {


    @Resource
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    /**
     * 获取索引对应的别名
     */
    @PostMapping("getAliasesForIndex")
    public Map<String, Set<AliasData>> getAliasesForIndex(@RequestBody String[] index) {
        IndexOperations indexOperations = elasticsearchRestTemplate.indexOps(FoodBlog.class);
        Map<String, Set<AliasData>> aliasesForIndex = indexOperations.getAliasesForIndex(index);
        return aliasesForIndex;
    }


    @GetMapping("/search")
    public ResponseEntity<SearchHits<ChargeDetailRecord_V1>> search() {
        IndexCoordinates blog = IndexCoordinates.of(ChargeDetailRecord_V1.class.getAnnotation(TypeAlias.class).value());
        Query query = elasticsearchRestTemplate.matchAllQuery();
        SearchHits<ChargeDetailRecord_V1> search = elasticsearchRestTemplate.search(query, ChargeDetailRecord_V1.class, blog);
        return ResponseEntity.ok(search);
    }

    /**
     * 第一步 创建 new Index
     *
     * @return
     */
    @PostMapping("createIndex")
    public Object createIndex() {
        IndexOperations indexOperations = elasticsearchRestTemplate.indexOps(ChargeDetailRecord.class);
        indexOperations.create();
        return indexOperations.putMapping();
    }

    /**
     * 第二步迁移数据 old index -> new Index
     *
     * @return
     */
    @PostMapping("reindex")
    public ResponseEntity<ReindexResponse> reindex() {
        IndexCoordinates sourceIndex = elasticsearchRestTemplate.indexOps(ChargeDetailRecord.class).getIndexCoordinates();
        IndexCoordinates destIndex = elasticsearchRestTemplate.indexOps(ChargeDetailRecord_V1.class).getIndexCoordinates();
        ReindexRequest.ReindexRequestBuilder builder = ReindexRequest.builder(sourceIndex, destIndex);
        ReindexResponse reindexResponse = elasticsearchRestTemplate.reindex(builder.build());
        return ResponseEntity.ok(reindexResponse);
    }


    /**
     * 第三步 add alias to new Index
     *
     * @return
     */
    @PostMapping("/alias")
    public ResponseEntity<Object> addAlias() {
        AliasActions aliasActions = new AliasActions();
        AliasActionParameters.Builder builder = AliasActionParameters.builder();
        builder.withAliases(ChargeDetailRecord_V1.class.getAnnotation(TypeAlias.class).value());
        builder.withIndices(ChargeDetailRecord_V1.class.getAnnotation(Document.class).indexName());
        AliasAction aliasAction = new AliasAction.Add(builder.build());
        aliasActions.add(aliasAction);
        return ResponseEntity.ok(elasticsearchRestTemplate.indexOps(ChargeDetailRecord_V1.class).alias(aliasActions));
    }

    /**
     * 第四步  remove alias  on old index
     *
     * @return
     */
    @DeleteMapping("/alias")
    public ResponseEntity<Object> removeAlias() {
        AliasActions aliasActions = new AliasActions();
        AliasActionParameters.Builder builder = AliasActionParameters.builder();
        builder.withAliases(ChargeDetailRecord.class.getAnnotation(TypeAlias.class).value());
        builder.withIndices(ChargeDetailRecord.class.getAnnotation(Document.class).indexName());
        AliasAction aliasAction = new AliasAction.Remove(builder.build());
        aliasActions.add(aliasAction);
        return ResponseEntity.ok(elasticsearchRestTemplate.indexOps(ChargeDetailRecord.class).alias(aliasActions));
    }

    /**
     * 第五步  delete old index
     *
     * @return
     */
    @DeleteMapping("/index")
    public ResponseEntity<Object> deleteIndex() {
        return ResponseEntity.ok(elasticsearchRestTemplate.indexOps(ChargeDetailRecord.class).delete());
    }
}

js data索引 date索引,js data索引 date索引_spring_03,第3张

 


https://www.xamrdz.com/backend/38k1931224.html

相关文章: