前言
- 本篇文章 基于官方文档 删改,版本 :elasticsearch-6.2.2 spring boot 2.0
- Elasticsearch 是一个分布式、可扩展、实时的搜索与数据分析引擎
- 全文搜索,结构化数据的实时统计,结构化搜索、数据分析、复杂的语言处理、地理位置和对象间关联关系等,数据建模来充分利用 Elasticsearch 的水平伸缩性,以及在生产环境中如何配置和监视你的集群
- 适合人群:有一定的编程基础,虽然不是必须的,但有用过 SQL 和关系数据库会更佳
- 本书的最后一部分是非常重要的,包含所有你需要知道的用以避免系统崩溃的知识
- api文档适合人群:参考文档是优秀的 前提是你知道你在寻找什么。它假定你已经熟悉信息检索的概念、分布式系统原理、Query DSL 和许多其他相关的概念
- ==这是一个问题,我该怎么解决?如何对候选方案进行权衡取舍?==
- ==需要理解 es内部逻辑==
- 这本权威指南不仅帮助你学习 Elasticsearch,而且带你接触更深入、更有趣的话题,如 集群内的原理 、 分布式文档存储 、 执行分布式检索 和 分片内部原理 ,这些虽然不是必要的阅读却能让你深入理解其内在机制。
- 应该学会:
- 基本的搜索操作
- 管理你的索引
- 将 Elasticsearch 与你的应用程序集成
- 了解分布式处理的过程
- 如何索引和查询你的数据,并借助一些更高级的特性,如邻近词(word proximity)和部分匹配(partial matching)。你将了解相关度评分是如何工作的以及如何控制它来确保第一页总是返回最佳的搜索结果
- 解决如何有效使用分析器和查询来处理语言的头痛问题
- 字母表和排序,还会涉及到词干提取、停用词、同义词和模糊匹配
- 讨论聚合(aggregations)和分析,对你的数据进行摘要化和分组来呈现总体趋势
- 支持的两种地理位置检索方式:经纬坐标点和复杂的地理形状(geo-shapes)
- 为你的数据建模
- 如何设计索引来匹配你系统中的数据流
- 生产环境上线的重要配置、监控点以及如何诊断以避免出现问题
概念
- 一个文档代表一个雇员
- 存储数据到 Elasticsearch 的行为叫做 索引
- 索引一个文档之前,需要确定将文档存储在哪里
- 索引有两层意思,名词:存储关系的地方 动词:存储一个文档到一个索引
- 倒排索引和关系型数据库索引一致
- 一个文档中的每一个属性都是 被索引 的(有一个倒排索引)和可搜索的。一个没有倒排索引的属性是不能被搜索到的
- number_of_replicas 是数据备份数,如果只有一台机器,设置为0,否则集群健康值会是yellow
- number_of_shards是数据分片数,默认为5,有时候设置为3
部署
elasticsearch启动
Linux:
cd elasticsearch-
./bin/elasticsearch
如果你想把 Elasticsearch 作为一个守护进程在后台运行,那么可以在后面添加参数 -d
而一个 集群 是一组拥有相同 cluster.name 的节点, 他们能一起工作并共享数据,还提供容错与可伸缩性
Java 客户端作为节点必须和 Elasticsearch 有相同的 主要 版本;否则,它们之间将无法互相理解。
修改配置文件:
elasticsearch-6.2.2\config
network.host: 10.11.3.182 (修改为局域网Ip地址)
transport.tcp.port: 9300
transport.tcp.compress: true
http.port: 9200
Windows:
进入elasticsearch bin目录下执行elasticsearch.bat
kibana安装插件 :Windows :kibana-plugin.bat install url
需求
- 业务需求:
- 支持包含多值标签、数值、以及全文本的数据
- 检索任一雇员的完整信息
- 允许结构化搜索,比如查询 30 岁以上的员工
- 允许简单的全文搜索以及较复杂的短语搜索
- 支持在匹配文档内容中高亮显示搜索片段
- 支持基于数据创建和管理分析仪表盘
开发
API
- 删除索引
DELETE /megacorp
- 创建索引 并索引文档或修改文档: 无需创建一个索引或指定每个属性的数据类型之类的,可以直接只索引一个文档。Elasticsearch 默认地完成其他一切,因此所有必需的管理任务都在后台使用默认设置完成
PUT /megacorp/employee/1
{
"first_name" : "John",
"last_name" : "Smith",
"age" : 25,
"about" : "I love to go rock climbing",
"interests": [ "sports", "music" ]
}
2·修改number_of_replicas数量 否则集群健康值为yellow
http://10.11.3.182:9100/_settings
{ "index" : { "number_of_replicas" : 0 } }
3·查看 和删除索引文档
GET /megacorp/employee/1
DELETE /megacorp/employee/1
4·搜索
搜索所有
GET /megacorp/employee/_search
搜索指定字段
GET /megacorp/employee/_search?q=last_name:Smith
查询表达式搜索指定字段 领域特定语言 (DSL)
GET /megacorp/employee/_search
{
"query": {
"match": {
"last_name": "smith"
}
}
}
范围搜索
GET /megacorp/employee/_search
{
"query": {
"bool": {
"must": [
{
"term": {
"last_name.keyword": "Smith"
}
},
{
"range": {
"age": {
"gt": "30"
}
}
}
]
}
}
}
全文搜索
返回包含rock或climbing的结果
GET /megacorp/employee/_search
{
"query" : {
"match" : {
"about" : "rock climbing"
}
}
}
短语搜索
返回精确包含rock climbing的结果
GET /megacorp/employee/_search
{
"query" : {
"match_phrase" : {
"about" : "rock climbing"
}
}
}
高亮搜索
about 属性匹配的文本片段,并以 HTML 标签 <em></em> 封装
GET /megacorp/employee/_search
{
"query" : {
"match_phrase" : {
"about" : "rock climbing"
}
},
"highlight": {
"fields" : {
"about" : {}
}
}
}
高亮搜索标签设置
{
"query": {
"match_phrase": {
"about": "rock climbing"
}
},
"highlight": {
"pre_tags": [
"<tag1>"
],
"post_tags": [
"</tag1>"
],
"fields": {
"about": { }
}
}
}
单独给指定字段设置标签
{
"query": {
"match_phrase": {
"about": "rock climbing"
}
},
"highlight": {
"require_field_match": false,
"fields": {
"about": {
"pre_tags": [
"<em>"
],
"post_tags": [
"</em1>"
]
}
}
}
}
统计数组字段中出现最高的词语
需要先设置字段fielddata为true
PUT /megacorp/_mapping/employee/
{
"properties": {
"interests": {
"type": "text",
"fielddata": true
}
}
}
GET /megacorp/employee/_search
{
"aggs": {
"all_interests": {
"terms": {
"field": "interests"
}
}
}
}
添加条件聚合统计查询
GET /megacorp/employee/_search
{
"query": {
"match": {
"last_name": "smith"
}
},
"aggs": {
"all_interests": {
"terms": {
"field": "interests"
}
}
}
}
统计每个聚合组的平均年龄
GET /megacorp/employee/_search
{
"aggs" : {
"all_interests" : {
"terms" : { "field" : "interests" },
"aggs" : {
"avg_age" : {
"avg" : { "field" : "age" }
}
}
}
}
}
聚合查询类似于关系型数据库的group by
分布式特性
Elasticsearch 尽可能地屏蔽了分布式系统的复杂性。这里列举了一些在后台自动执行的操作:
分配文档到不同的容器 或 分片 中,文档可以储存在一个或多个节点中
按集群节点来均衡分配这些分片,从而对索引和搜索过程进行负载均衡
复制每个分片以支持数据冗余,从而防止硬件故障导致的数据丢失
将集群中任一节点的请求路由到存有相关数据的节点
集群扩容时无缝整合新节点,重新分配分片以便从离群节点恢复
==对于 Elasticsearch 知道得越多,就越有生产效率。告诉 Elasticsearch 越多的领域知识,就越容易进行结果调优。==
java 代码
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
1·pojo
package com.es.demo.pojo;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import java.io.Serializable;
/**
* 说明:
*
* @author WangBin
* @version V1.0
* @since 2018.04.10
*/
@Document(indexName="megacorp",type="employee",replicas=0)
public class Employee implements Serializable {
@Id
private Long id;
private String first_name;
private String last_name;
private int age;
private String about;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getFirst_name() {
return first_name;
}
public void setFirst_name(String first_name) {
this.first_name = first_name;
}
public String getLast_name() {
return last_name;
}
public void setLast_name(String last_name) {
this.last_name = last_name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getAbout() {
return about;
}
public void setAbout(String about) {
this.about = about;
}
@Override
public String toString() {
return "Employee{" +
"id=" + id +
", first_name='" + first_name + '\'' +
", last_name='" + last_name + '\'' +
", age=" + age +
", about='" + about + '\'' +
'}';
}
}
2·dao
package com.es.demo.dao;
import com.es.demo.pojo.Employee;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Component;
/**
* 说明:
*
* @author WangBin
* @version V1.0
* @since 2018.04.10
*/
@Component
public interface EmployeeSearchRepository extends ElasticsearchRepository<Employee,Long> {
}
3·service
package com.es.demo.service;
public interface TestEsService {
void query();
void save();
void delate();
}
package com.es.demo.service;
import com.es.demo.dao.EmployeeSearchRepository;
import com.es.demo.pojo.Employee;
import org.elasticsearch.index.query.QueryStringQueryBuilder;
import org.elasticsearch.index.query.SimpleQueryStringBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Iterator;
/**
* 说明:
*
* @author WangBin
* @version V1.0
* @since 2018.04.10
*/
@Service
public class TestEsServiceImpl implements TestEsService{
@Autowired
private EmployeeSearchRepository repository;
@Override
public void query() {
HashMap map = new HashMap();
map.put("","");
System.err.println("查询全部");
Iterable<Employee> all = repository.findAll();
for (Iterator iter = all.iterator(); iter.hasNext();) {
Employee employee = (Employee)iter.next();
System.err.println(employee);
}
System.err.println("部分查询");
QueryStringQueryBuilder builder = new QueryStringQueryBuilder("spring AND java OR ss");
builder.field("about");
all = repository.search(builder);
for (Iterator iter = all.iterator(); iter.hasNext();) {
Employee employee = (Employee)iter.next();
System.err.println(employee);
}
}
@Override
public void save() {
Employee employee = new Employee();
employee.setFirst_name("Wang");
employee.setLast_name("Bin");
employee.setAge(26);
employee.setAbout("java 123");
employee.setId(1L);
repository.save(employee);
employee.setFirst_name("Wang");
employee.setLast_name("123");
employee.setAge(27);
employee.setAbout("spring boot");
employee.setId(2L);
repository.save(employee);
employee.setFirst_name("Wang");
employee.setLast_name("123");
employee.setAge(28);
employee.setAbout("java : spring boot");
employee.setId(2L);
repository.save(employee);
}
@Override
public void delate() {
repository.deleteAll();
}
}
//查询方式
//QueryStringQueryBuilder builder = new QueryStringQueryBuilder("spring AND java OR ss");