一、ElasticSearch简介
ES是一款分布式的全文检索框架,底层基于Lucene实现,天然分布式,p2p架构,不支持事务,采用倒排索引提供全文检索。较为广泛的应用于全文检索和统计分析的聚合查询中。
二、ES较之于mysql的优势
ES是一个支持分布式的框架,它的每个node都可以接收读request,然后该node会把request分发到含有该index的shard的节点上,对应的节点会查询、并计算出符合条件的文档,排序后结果汇聚到分发request的node(所以查询请求默认会轮循的将发送到各个节点上,防止请求全部打到一个节点),由该node将数据返回给client。相比于mysql的扩展性较差的单机模式具有很强的性能提升。
再者,ES具有较强的聚合查询能力,虽然mysql也提供有group by等用来聚合查询的语句,但是遇到较为复杂的统计查询时,mysql显然是力不从心的,这时候es的聚合查询能力的优势就显得尤为重要了。
举个例子:倘若我们要统计一批数据中startDate和endDate时间范围内每七天一次统计的数据条数,并将时间作为横轴,数据条数作为纵轴供前端渲染显示,这时候mysql的简易聚合查询能力就会显得很难,即使写出了这样的sql语句,也将会很复杂,但我们利用es原生的聚合查询api就可以很容易实现这个需求。
curl -XGET -H 'Content-Type: application/json' 'http://localhost:9200/students/_search?pretty=true' -d '
{
"aggs" : {
"sentdate_range_search" : {
"date_range" : {
"field" : "updateTime",
"time_zone": "UTC",
"interval":"7day",
"format" : "yyyy-MM-dd HH:mm:ssZZ",
"ranges" : [
{ "from" : "2010-05-07 11:22:34+0000", "to" : "2011-05-07 11:22:34+0000"}
]
}
}
}
}'
三、es本地下载启动
brew install elasticsearch
再执行elasticsearch命令启动es:默认端口号为9200
四、mysql数据表建立及logStash配置实现mysql、es数据同步
首先在本地建立一张数据表:
CREATE TABLE student(
id INT PRIMARY KEY AUTO_INCREMENT ,
name VARCHAR(200) not null,
shcool VARCHAR(200) not null,
update_time datetime not null,
have_money bigint not null,
)
logStash安装配置:
brew install logstash
cd /usr/local/Cellar/logstash/7.12.1/bin
编写配置文件:
input {
jdbc {
### 连接的mysql数据库相关信息
jdbc_connection_string => "jdbc:mysql://127.0.0.1:3306/test"
jdbc_user => "root"
jdbc_password => "***"
### jdbc驱动jar包
jdbc_driver_library => "/usr/local/Cellar/logstash/7.12.1/libexec/logstash-core/lib/jars/mysql-connector-java-8.0.25.jar"
jdbc_driver_class => "com.mysql.jdbc.Driver"
jdbc_paging_enabled => "true"
jdbc_page_size => "50000"
### 用于同步的字段,上面建的mysql表中的update_time字段
tracking_column => update_time
record_last_run => true
### 在这个目录下建一个文件用来存储上一次数据同步的时间
last_run_metadata_path => "/usr/local/opt/logstash/lastrun/.logstash_jdbc_last_run"
jdbc_default_timezone => "Asia/Shanghai"
### 当表中的update_time时间大于上一次同步的时间,将其加载到es中
statement_filepath => "SELECT * FROM goods WHERE update_time > :sql_last_value"
clean_run => false
### 每一分钟同步一次
schedule => "* * * * *"
type => "std"
}
}
output {
elasticsearch {
### es地址和索引、type
hosts => "http://localhost:9200"
index => "students"
document_type => "student"
document_id => "%{id}"
}
stdout{
codec => json_lines
}
}
启动logstash
./logstash -f jdbc.conf
五、Springboot整合es
新建Springboot项目,项目目录
配置文件
spring:
main:
allow-bean-definition-overriding: true
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/test
username: root
password: Lliulei919
jpa:
show-sql: true
data:
elasticsearch:
cluster-name: ll
cluster-nodes: 127.0.0.1:9200
repositories:
enabled: true
jpa循环往sql中插入2000份数据
public void startInjectData() {
List<Student> list = new ArrayList<>();
Date currentDate = new Date();
for(int i=0;i<2000;i++){
Student student = new Student();
student.setName("zhangsan" + i);
student.setSchool("Cleton" + i);
student.setHomeTown("beijing");
student.setHaveMoney(2000L + i * 10);
student.setUpdateTime(new Date(currentDate.getTime() - 1000 * i * 60 * 60 * 24) );
list.add(student);
}
studentSqlRepository.saveAll(list);
}
public interface StudentRepository extends JpaRepository<Student,Integer> {
Integer countByHaveMoneyBetween(Long start, Long end);
}
springBoot整合es进行简单查询
public interface StudentEsRepository extends ElasticsearchRepository<StudentVO,Integer> {
}
ElasticsearchRepository具有基础的crud查询方法,直接调用即可操作es中的数据,与jpa类似
进行复杂聚合查询
选用
@Autowired private ElasticsearchRestTemplate esTemplate;
进行聚合查询
AggregationBuilder aggregation =
AggregationBuilders
.dateHistogram("es_count")
.field("update_time")
.fixedInterval(DateHistogramInterval.days(7));
查询条件:
NativeSearchQuery searchQueryBuilder = new NativeSearchQueryBuilder()
.withQuery(QueryBuilders.rangeQuery("update_time").from(startDate).to(endDate))
.addAggregation(aggregation)
.build();
这样的聚合查询条件也就可以解决‘统计一批数据中startDate和endDate时间范围内每七天一次统计的数据条数,并将时间作为横轴,数据条数作为纵轴供前端渲染显示’这个需求了
所以对于较为复杂的统计查询,只需要编写聚合查询条件,即可相比于mysql得到较为优秀的查询性能了。