Command Query Responsibility Segregation (CQRS) separates the behavior of modifying (Command, add, delete, modify, modify the system status) and query (Query, query, will not modify the system status) from the business. This makes the logic clearer and facilitates targeted optimization of different parts.
CQRS has the following points:
1. The division of labor is clear and you can be responsible for different parts;
2. Separating the responsibilities of business commands and queries can improve the performance, scalability and security of the system. In addition, it can maintain a high degree of flexibility in the evolution of the system, and prevent the occurrence of changes in one party in the query or modification in the CRUD mode, resulting in problems with the other party;
3. Clear logic and can see that those behaviors or operations in the system have caused changes in the state of the system;
4. You can go from data-driven to task-driven and event-Driven.
Therefore, Command uses databases, and Query uses Elasticsearch with more efficient query.
How to ensure consistency between database and Elasticsearch data?
We can use event-Driven, that is, Spring Data's Domain Event synchronization data, please refer to the article: http://www.VeVB.COM/article/135604.htm.
When an old database has a large amount of data that needs to be imported into Elasticsearch, you can refer to the article: http://www.VeVB.COM/article/135426.htm
Spring Data Elasticsearch uses transport client, while Elasticsearch's official website recommends using REST client. There are still problems with Alibaba Cloud's Elasticsearch using transport client, and Alibaba Cloud recommends using REST client.
This example uses Spring Data Jest link Elasticsearch (currently only supports spring boot2.0 or above). The version of Elasticsearch is: 5.5.3
1. Project construction
1.pom dependencies are as follows:
<dependency> <groupId>com.github.vanroy</groupId> <artifactId>spring-boot-starter-data-jest</artifactId> <version>3.0.0.RELEASE</version></dependency><dependency> <groupId>io.searchbox</groupId> <artifactId>jest</artifactId> <version>5.3.2</version></dependency>
2. Configuration file
spring: data: jest: uri: http://127.0.0.1:9200 username: elastic password: changeme
2. Construct query conditions
Take a simple entity class as an example
package com.hfcsbc.esetl.domain;import lombok.Data;import org.springframework.data.elasticsearch.annotations.Document;import org.springframework.data.elasticsearch.annotations.Field;import org.springframework.data.elasticsearch.annotations.FieldType;import javax.persistence.Entity;import javax.persistence.Id;import javax.persistence.OneToOne;import java.util.Date;import java.util.List;/** * Create by pengchao on 2018/2/23 */@Document(indexName = "person", type = "person", shards = 1, replicas = 0, refreshInterval = "-1")@Entity@Datapublic class Person { @Id private Long id; private String name; @OneToOne @Field(type = FieldType.Nested) private List<Address> address; private Integer number; private Integer status; private Date birthDay;} package com.hfcsbc.esetl.domain;import lombok.Data;import javax.persistence.Entity;import javax.persistence.Id;/** * Create by pengchao on 2018/2/23 */@Entity@Datapublic class Address { @Id private Long id; private String name; private Integer number;} 1. Query based on multiple states (similar to sql's in)
BoolQuiller orderStatusCondition = QueryBuilders.boolQuery() .should(QueryBuilders.termQuery("status", 1)) .should(QueryBuilders.termQuery("status", 2)) .should(QueryBuilders.termQuery("status", 3)) .should(QueryBuilders.termQuery("status", 4)) .should(QueryBuilders.termQuery("status", 5)); 2.and link query (similar to sql and)
BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();queryBuilder .must(queryBuilder1) .must(queryBuilder2) .must(queryBuilder3);
3.range query (similar to SQL between.. and ..)
The code copy is as follows:
QueryBuilder rangeQuery = QueryBuilders.rangeQuery("birthDay").from(yesterday).to(today);
4. Nested object query
The code copy is as follows:
QueryBuilder queryBuilder = QueryBuilders.nestedQuery("nested", QueryBuilders.termQuery("address.id", 100001), ScoreMode.None);
ScoreMode: Defines how score is used in other join side. If you don't pay attention to scoring, we just need to set it to ScoreMode.None. This method will ignore the score and will therefore be more efficient and save memory
3. Obtain statistics
1. Unnecked data sum
SumAggregationBuilder sumBuilder = AggregationBuilders.sum("sum").field("number");SearchQuery searchQuery = new NativeSearchQueryBuilder() .withIndices(QUERY_INDEX) .withTypes(QUERY_TYPE) .withQuery(boolQueryBuilder) .addAggregation(sumBuilder).build(); AggregatedPage<ParkingOrder> account = (AggregatedPage<ParkingOrder>) esParkingOrderRepository.search(EsQueryBuilders.buildYesterdayArrearsSumQuery(employeeId));int sum = account.getAggregation("sum", SumAggregation.class).getSum().intValue(); 2. Nested data sum
SumAggregationBuilder sumBuilder = AggregationBuilders.sum("sum").field("adress.num");AggregationBuilder aggregationBuilder = AggregationBuilders.nested("nested", "adress").subAggregation(sumBuilder);SearchQuery searchQuery = new NativeSearchQueryBuilder() .withIndices(QUERY_INDEX) .withTypes(QUERY_TYPE) .withQuery(boolQueryBuilder) .addAggregation((AbstractAggregationBuilder) aggregationBuilder).build();AggregatedPage<ParkingOrder> account = (AggregatedPage<ParkingOrder>) esParkingOrderRepository.search(EsQueryBuilders.buildYesterdayArrearsSumQuery(employeeId));int sum = account.getAggregation("nested", SumAggregation.class).getAggregation("sum", SumAggregation.class).getSum().intValue();The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.