(1). 需求
以订单和订单详细为模型,把数据同步到ES中,进行检索.
(2). 创建索引库
DELETE /order_index
# 创建索引库
PUT /order_index
{
"settings": {
"index":{
"number_of_shards":"1",
"number_of_replicas":"0"
}
},
"mappings": {
"properties":{
"order" : {
"properties":{
"order_id": { "type": "long" },
"order_no": { "type": "text" , "analyzer" : "ik_max_word" },
"customer_id": { "type": "long" },
"customer_name": { "type": "keyword" },
"customer_phone": { "type": "keyword" },
"customer_address": { "type": "text" , "analyzer" : "ik_max_word" },
"merchant_id": { "type": "long" },
"total_money" : { "type" : "double" },
"order_status" : { "type" : "keyword" }
}
},
"order_detail" : {
"properties":{
"order_detail_id": { "type": "long" },
"order_id": { "type": "long" },
"goods_id": { "type": "long" },
"goods_no": { "type": "text" , "analyzer" : "ik_max_word" },
"goods_name" : { "type": "text" , "analyzer" : "ik_max_word" },
"goods_img" : { "type" : "keyword" },
"price" : { "type" : "double" },
"buy_num" : { "type": "integer" }
}
},
"relation" : {
"type" : "join",
"relations" : {
"order" : ["order_detail"]
}
}
}
}
}
(3). 模拟下订单业务
package help.lixin.erp;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import help.lixin.erp.entity.OrderDetail;
import help.lixin.erp.entity.Orders;
import help.lixin.erp.service.IOrdersService;
@RunWith(SpringRunner.class)
@SpringBootTest
public class BuyTest {
@Autowired
private IOrdersService ordersService;
@Test
public void testBuy1() {
long orderId = 1L;
List<OrderDetail> details = new ArrayList<OrderDetail>();
OrderDetail detail1 = new OrderDetail();
detail1.setOrderDetailId(11L);
detail1.setOrderId(orderId);
detail1.setGoodsId(1L);
detail1.setGoodsName("Apple iPhone 11 (A2223) 128GB 黑色 移动联通电信4G手机 双卡双待");
detail1.setGoodsNo("202004020000001");
detail1.setGoodsImg("/goods1.jpg");
detail1.setPrice(new BigDecimal("4899.00"));
detail1.setBuyNum(1);
OrderDetail detail2 = new OrderDetail();
detail2.setOrderDetailId(22L);
detail2.setOrderId(orderId);
detail2.setGoodsId(103L);
detail2.setGoodsName("联想(Lenovo)小新Air14锐龙版14英寸全面屏轻薄笔记本电脑(6核12线程R5-5500U 16G 512G 高色域)深空灰");
detail2.setGoodsNo("20200402000000103");
detail2.setGoodsImg("/goods103.jpg");
detail2.setPrice(new BigDecimal("4699.00"));
detail2.setBuyNum(1);
details.add(detail1);
details.add(detail2);
// 计算总金额
BigDecimal totalMoney = details.stream()
.map(detail -> detail.getPrice().multiply(new BigDecimal(detail.getBuyNum())))
.reduce(BigDecimal.ZERO, BigDecimal::add);
Orders orders = new Orders();
orders.setOrderId(orderId);
orders.setOrderNo("O00000000001");
orders.setVersion(1);
orders.setOrderStatus("1");
orders.setCustomerId(77777L);
orders.setCustomerName("张三");
orders.setCustomerPhone("13799999999");
orders.setCustomerAddress("广东省深圳市宝安区");
orders.setMerchantId(88888L);
orders.setTotalMoney(totalMoney);
ordersService.createOrder(orders, details);
}
@Test
public void testBuy2() {
long orderId = 2L;
List<OrderDetail> details = new ArrayList<OrderDetail>();
OrderDetail detail1 = new OrderDetail();
detail1.setOrderDetailId(33L);
detail1.setOrderId(orderId);
detail1.setGoodsId(2L);
detail1.setGoodsName("Redmi 9A 5000mAh大电量 大屏幕大字体大音量 1300万AI相机 八核处理器 人脸解锁 4GB+64GB 砂石黑 游戏智能手机 小米 红米");
detail1.setGoodsNo("202004020000002");
detail1.setGoodsImg("/goods2.jpg");
detail1.setPrice(new BigDecimal("599.00"));
detail1.setBuyNum(2);
OrderDetail detail2 = new OrderDetail();
detail2.setOrderDetailId(44L);
detail2.setOrderId(orderId);
detail2.setGoodsId(3L);
detail2.setGoodsName("Redmi Note 9 5G 天玑800U 18W快充 4800万超清三摄 云墨灰 6GB+128GB 游戏智能手机 小米 红米");
detail2.setGoodsNo("202004020000003");
detail2.setGoodsImg("/goods3.jpg");
detail2.setPrice(new BigDecimal("1299.00"));
detail2.setBuyNum(3);
details.add(detail1);
details.add(detail2);
// 计算总金额
BigDecimal totalMoney = details.stream()
.map(detail -> detail.getPrice().multiply(new BigDecimal(detail.getBuyNum())))
.reduce(BigDecimal.ZERO, BigDecimal::add);
Orders orders = new Orders();
orders.setOrderId(orderId);
orders.setOrderNo("O00000000002");
orders.setVersion(1);
orders.setOrderStatus("1");
orders.setCustomerId(66666L);
orders.setCustomerName("张三");
orders.setCustomerPhone("13788888888");
orders.setCustomerAddress("广东省深圳市宝安区");
orders.setMerchantId(88888L);
orders.setTotalMoney(totalMoney);
ordersService.createOrder(orders, details);
}
@Test
public void testBuy3() {
long orderId = 3L;
List<OrderDetail> details = new ArrayList<OrderDetail>();
OrderDetail detail1 = new OrderDetail();
detail1.setOrderDetailId(55L);
detail1.setOrderId(orderId);
detail1.setGoodsId(102L);
detail1.setGoodsName("戴尔DELL成就3400 14英寸轻薄性能商务全面屏笔记本电脑(11代i5-1135G7 16G 512G)一年上门+7x24远程服务");
detail1.setGoodsNo("20200402000000102");
detail1.setGoodsImg("/goods102.jpg");
detail1.setPrice(new BigDecimal("4999.00"));
detail1.setBuyNum(1);
OrderDetail detail2 = new OrderDetail();
detail2.setOrderDetailId(66L);
detail2.setOrderId(orderId);
detail2.setGoodsId(101L);
detail2.setGoodsName("联想小新Air15 2021锐龙R7 金属超轻薄笔记本电脑 高色域全面屏 学生网课办公 设计师游戏本 八核R7-4800U 16G 512G固态 标配 高色域全面屏【低蓝光护眼无闪烁】");
detail2.setGoodsNo("20200402000000101");
detail2.setGoodsImg("/goods101.jpg");
detail2.setPrice(new BigDecimal("5799.00"));
detail2.setBuyNum(1);
details.add(detail1);
details.add(detail2);
// 计算总金额
BigDecimal totalMoney = details.stream()
.map(detail -> detail.getPrice().multiply(new BigDecimal(detail.getBuyNum())))
.reduce(BigDecimal.ZERO, BigDecimal::add);
Orders orders = new Orders();
orders.setOrderId(orderId);
orders.setOrderNo("O00000000003");
orders.setVersion(1);
orders.setOrderStatus("1");
orders.setCustomerId(55555L);
orders.setCustomerName("李四");
orders.setCustomerPhone("13755555");
orders.setCustomerAddress("湖南省长沙市");
orders.setMerchantId(999999L);
orders.setTotalMoney(totalMoney);
ordersService.createOrder(orders, details);
}
}
(4). 手动测试,同步MySQL数据到ES
注意:父子文档的ID不能相同,否则,会覆盖文档的.
package help.lixin.erp;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.apache.http.HttpHost;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import help.lixin.erp.entity.OrderDetail;
import help.lixin.erp.entity.Orders;
import help.lixin.erp.service.IOrderDetailService;
import help.lixin.erp.service.IOrdersService;
@RunWith(SpringRunner.class)
@SpringBootTest
public class SyncDataToESTest {
@Autowired
private IOrdersService ordersService;
@Autowired
private IOrderDetailService orderDetailService;
private RestHighLevelClient client;
@Before
public void init() {
RestClientBuilder restClientBuilder = RestClient.builder( //
new HttpHost("127.0.0.1", 9200, "http")
);
this.client = new RestHighLevelClient(restClientBuilder);
}
@Test
public void testSyncDataToEs() {
List<Orders> list = ordersService.list();
list.stream().map(order -> {
Long orderId = order.getOrderId();
List<OrderDetail> details = orderDetailService.list(Wrappers.<OrderDetail>query().eq("order_id", orderId));
order.setDetails(details);
return order;
}).forEach(item -> {
IndexRequest parentIndex = buildOrder(item);
List<IndexRequest> parentIndexs = Collections.singletonList(parentIndex);
List<IndexRequest> childIndexs = buildOrderDetails(item);
execute(parentIndexs);
execute(childIndexs);
});
}
public void execute(Collection<IndexRequest> indexRequests) {
indexRequests.stream().forEach(indexRequest -> {
try {
IndexResponse response = client.index(indexRequest, RequestOptions.DEFAULT);
System.out.println("index:" + response.getIndex());
System.out.println("type:" + response.getType());
System.out.println("id:" + response.getId());
} catch (IOException e) {
throw new RuntimeException(e.getMessage());
}
});
}
public IndexRequest buildOrder(Orders order) {
Map<String, Object> relation = new HashMap<String, Object>();
relation.put("name", "order");
Map<String, Object> source = new HashMap<String, Object>();
source.put("order_id", order.getOrderId());
source.put("order_id", order.getOrderId());
source.put("order_no", order.getOrderNo());
source.put("customer_id", order.getCustomerId());
source.put("customer_name", order.getCustomerName());
source.put("customer_phone", order.getCustomerPhone());
source.put("customer_address", order.getCustomerAddress());
source.put("merchant_id", order.getMerchantId());
source.put("total_money", order.getTotalMoney());
source.put("order_status", order.getOrderStatus());
// setting relation
source.put("relation", relation);
IndexRequest indexRequest = new IndexRequest();
indexRequest.index("order_index");
indexRequest.id(order.getOrderId().toString());
indexRequest.source(source);
return indexRequest;
}
public List<IndexRequest> buildOrderDetails(Orders order) {
String orderId = order.getOrderId().toString();
return order.getDetails().stream() //
.filter(item -> null != item) //
.map(detail -> {
Map<String, Object> relation = new HashMap<String, Object>();
relation.put("name", "order_detail");
relation.put("parent", orderId);
Map<String, Object> source = new HashMap<String, Object>();
source.put("order_detail_id", detail.getOrderDetailId());
source.put("order_id", detail.getOrderId().toString());
source.put("goods_id", detail.getGoodsId());
source.put("goods_no", detail.getGoodsNo());
source.put("goods_name", detail.getGoodsName());
source.put("goods_img", detail.getGoodsImg());
source.put("price", detail.getPrice().doubleValue());
source.put("buy_num", detail.getBuyNum());
// set releation
source.put("relation", relation);
IndexRequest indexRequest = new IndexRequest();
indexRequest.index("order_index");
indexRequest.id(detail.getOrderDetailId().toString());
indexRequest.routing(orderId);
indexRequest.source(source);
return indexRequest;
}).collect(Collectors.toList());
}
}
(5). 通过DSL检索文档
# 需求:查询商户("88888")下,客户地址是:"深圳",并且,客户购买的商品名称包括有"联想"或"大电量"的数据.
# SELECT o.*
# FROM t_order o , t_order_detail d
# WHERE o.order_id = d.order_id
# AND o.merchant_id = 88888
# AND o.customer_address LIKE '%深圳%'
# AND ( d.goods_name LIKE '%联想%' OR d.goods_name LIKE '%大电量%' )
GET /order_index/_search
{
"query": {
"bool": {
"filter": [
{ "term" : { "merchant_id" : 88888 } } ,
{ "match" : { "customer_address" : "深圳" } }
],
"must": [
{
"has_child": {
"type": "order_detail",
"query": {
"bool": {
"should": [
{
"match": {
"goods_name": "大电量"
}
},
{
"match": {
"goods_name": "联想"
}
}
]
}
},
"inner_hits" : {}
}
}
]
}
}
}
# 需求:查询商户("88888")下,客户地址是:"深圳",并且,客户购买的商品名称包括有"联想"或"大电量"的数据.
# 与上面的功能一样,只是换了另一种写法而已(inner_hits只有:has_child支持).
# 1. 对子文档进行检索,返回,父文档信息
# 2. 对父文档进行二次检索.
GET /order_index/_search
{
"query": {
"bool": {
"must": [
{
"has_child": {
"type": "order_detail",
"query": {
"bool": {
"should": [
{
"match_phrase": {
"goods_name": "联想"
}
},
{
"match_phrase": {
"goods_name": "大电量"
}
}
]
}
}
,"inner_hits" : {}
}
},
{
"term": {
"merchant_id": {
"value": "88888"
}
}
},
{
"match_phrase": {
"customer_address": "深圳市"
}
}
]
}
},
"from": 0,
"size": 10
}
(6). 通过Java api检索文档
package help.lixin.erp;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import org.apache.http.HttpHost;
import org.apache.lucene.search.join.ScoreMode;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.InnerHitBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.join.query.HasChildQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class EsQueryTest {
private RestHighLevelClient client;
@Before
public void init() {
RestClientBuilder restClientBuilder = RestClient.builder( //
new HttpHost("127.0.0.1", 9200, "http")
);
this.client = new RestHighLevelClient(restClientBuilder);
}
/**
* 需求: <br/>
* SELECT o.* <br/>
* FROM t_order o , t_order_detail d <br/>
* WHERE o.order_id = d.order_id <br/>
* AND o.merchant_id = 88888 <br/>
* AND o.customer_address LIKE '%深圳市%' <br/>
* AND ( d.goods_name LIKE '%联想%' OR d.goods_name LIKE '%大电量%' )
*/
@SuppressWarnings("rawtypes")
@Test
public void query() {
// 构建订单详细信息过滤条件.( AND ( d.goods_name LIKE '%联想%' OR d.goods_name LIKE '%大电量%' )
// )
BoolQueryBuilder orderDetailBool = QueryBuilders.boolQuery();
orderDetailBool.should(QueryBuilders.matchQuery("goods_name", "大电量"));
orderDetailBool.should(QueryBuilders.matchQuery("goods_name", "联想"));
// 构建主从表查询
HasChildQueryBuilder hasChild = new HasChildQueryBuilder("order_detail", orderDetailBool, ScoreMode.None);
// fetch 子表(t_order_detail)的信息出来
hasChild.innerHit(new InnerHitBuilder());
// bool查询
BoolQueryBuilder bool = QueryBuilders.boolQuery();
// AND o.merchant_id = 88888
bool.filter(QueryBuilders.termQuery("merchant_id", 88888L));
// AND o.customer_address LIKE '%深圳市%'
// matchPhraseQuery:短语精准match
bool.filter(QueryBuilders.matchPhraseQuery("customer_address", "深圳市"));
// AND ( d.goods_name LIKE '%联想%' OR d.goods_name LIKE '%大电量%' )
bool.must(hasChild);
//
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(bool);
sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
SearchRequest searchRequest = new SearchRequest("order_index");
searchRequest.source(sourceBuilder);
try {
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("搜索到:" + response.getHits().getTotalHits().value + " 条数据");
SearchHits hits = response.getHits();
for (SearchHit hit : hits) {
String json = hit.getSourceAsString();
// 获取所有的子表(t_order_detail)信息
List<Map> childItems = new ArrayList<>();
hit.getInnerHits().forEach((k, v) -> {
SearchHit[] searchHits = v.getHits();
for (SearchHit searchHit : searchHits) {
childItems.add(searchHit.getSourceAsMap());
}
});
System.out.println(json);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
(7). DDL语句
DROP TABLE t_goods;
DROP TABLE t_orders;
CREATE TABLE t_orders(
order_id BIGINT NOT NULL COMMENT '订单id' ,
order_no VARCHAR(128) COMMENT '订单编号' ,
customer_id BIGINT COMMENT '买家id' ,
customer_name VARCHAR(1024) COMMENT '买家名称' ,
customer_phone VARCHAR(32) COMMENT '买家电话' ,
customer_address VARCHAR(32) COMMENT '买家地址' ,
merchant_id BIGINT COMMENT '商户id' ,
total_money DECIMAL(32,8) COMMENT '订单总金额' ,
order_status CHAR(1) COMMENT '订单状态 1:订单创建
2:订单支付中
3:订单出库中
4:订单完成
5:订单退货' ,
version INT COMMENT '乐观锁' ,
created_by VARCHAR(32) COMMENT '创建人' ,
created_time DATETIME COMMENT '创建时间' ,
updated_by VARCHAR(32) COMMENT '更新人' ,
updated_time DATETIME COMMENT '更新时间' ,
PRIMARY KEY (order_id)
) COMMENT = '订单信息';
ALTER TABLE t_orders COMMENT '订单信息';
DROP TABLE t_order_detail;
CREATE TABLE t_order_detail(
order_detail_id BIGINT NOT NULL COMMENT '订单信息id' ,
order_id BIGINT COMMENT '订单id' ,
goods_id BIGINT COMMENT '商品id' ,
goods_no VARCHAR(128) COMMENT '商品编号' ,
goods_name VARCHAR(1024) COMMENT '商品名称' ,
goods_img VARCHAR(128) COMMENT '商品图片' ,
price DECIMAL(32,8) COMMENT '价格' ,
buy_num INT COMMENT '购买数量' ,
version INT COMMENT '乐观锁' ,
created_by VARCHAR(32) COMMENT '创建人' ,
created_time DATETIME COMMENT '创建时间' ,
updated_by VARCHAR(32) COMMENT '更新人' ,
updated_time DATETIME COMMENT '更新时间' ,
PRIMARY KEY (order_detail_id)
) COMMENT = '订单详细信息';
ALTER TABLE t_order_detail COMMENT '订单详细信息';
(8). pom.xml
由于SpringBoot依赖了6.7.2版本,所以,需要自己排除,并设置成:7.1.0
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>help.lixin.erp</groupId>
<artifactId>erp-example</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>erp-example</name>
<url>http://maven.apache.org</url>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<elasticsearch.version>7.1.0</elasticsearch.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.1.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix</artifactId>
<version>2.1.1.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<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>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.48</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.4</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>7.1.0</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.1.0</version>
<!-- 设置排除 -->
<exclusions>
<exclusion>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
</exclusion>
<exclusion>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch-core</artifactId>
</exclusion>
<exclusion>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch-cli</artifactId>
</exclusion>
<exclusion>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch-secure-sm</artifactId>
</exclusion>
<exclusion>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch-x-content</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 重新添加指定版本 -->
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch-core</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch-cli</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch-secure-sm</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch-x-content</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.31</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
(9). 总结
ES并没有像MySQL那样,对Join查询支持比较好, 而且,官网或者第三方网站也好,对于父子文档只是用于案例,并没有做到真实案例来驱动,比如:既检索子文档,父文档也要参与检索.
至于,如何把MySQL的数据同步到ES中,这个需要Canal了,后续会写相应的blog.