ElasticSearch保姆级入门教程

Posted 芝士就是Power

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ElasticSearch保姆级入门教程相关的知识,希望对你有一定的参考价值。


一、初识ElasticSearch

  • elasticsearch是elastic stack的核心,负责存储、搜索、分析数据

  • Lucene是一个Java语言的搜索引擎类库,是Apache公司的顶级项目。
  • Lucene官方
  • Lucene优势:
    1. 易扩展
    2. 高性能(基于倒排索引)

  • mysql和elasticsearch相关概念
  • MySQL擅长:事务类的操作,可以确保数据的安全和一致性
  • Elasticsearch擅长:海量数据的搜索、分析、计算

二、安装Elasticsearch

2.1 创建网络

  • 因为我们还需要部署kibana容器,因此需要让es和kibana容器互联。这里先创建一个网络:
	docker network create es-net #创建网络

2.2 下载资源/加载镜像

ElasticSearch官网并且下载kibana依赖包
或者
采用镜像tar包

	docker load -i tar包 

2.3 运行

  • 运行docker命令,部署单点es
docker run -d \\
	--name es \\
    -e "ES_JAVA_OPTS=-Xms512m -Xmx512m" \\
    -e "discovery.type=single-node" \\
    -v es-data:/usr/share/elasticsearch/data \\
    -v es-plugins:/usr/share/elasticsearch/plugins \\
    --privileged \\
    --network es-net \\
    -p 9200:9200 \\
    -p 9300:9300 \\
elasticsearch:7.12.1
  • -e "cluster.name=es-docker-cluster":设置集群名称
  • -e "http.host=0.0.0.0":监听的地址,可以外网访问
  • -e "ES_JAVA_OPTS=-Xms512m -Xmx512m":内存大小
  • -e "discovery.type=single-node":非集群模式
  • -v es-data:/usr/share/elasticsearch/data:挂载逻辑卷,绑定es的数据目录
  • -v es-logs:/usr/share/elasticsearch/logs:挂载逻辑卷,绑定es的日志目录
  • -v es-plugins:/usr/share/elasticsearch/plugins:挂载逻辑卷,绑定es的插件目录
  • --privileged:授予逻辑卷访问权
  • --network es-net :加入一个名为es-net的网络中
  • -p 9200:9200:端口映射配置

在浏览器输入 ip:9200 即可看见一下消息说明 elasticsearch安装成功

2.4 部署kibana

  • kibana可以给我们提供一个elasticsearch的可视化界面,便于我们学习。

2.4.1 部署

docker run -d \\
--name kibana \\
-e ELASTICSEARCH_HOSTS=http://es:9200 \\
--network=es-net \\
-p 5601:5601  \\
kibana:7.12.1
  • 部署完成后 浏览器访问 ip:5601
  • --network es-net :加入一个名为es-net的网络中,与elasticsearch在同一个网络中
  • -e ELASTICSEARCH_HOSTS=http://es:9200":设置elasticsearch的地址,因为kibana已经与elasticsearch在一个网络,因此可以用容器名直接访问elasticsearch
  • -p 5601:5601:端口映射配置

2.5 安装IK分词器

  • IK分词器下载
  • 下载好后我们把IK分词器的资源放入到我们docker挂载的数据卷中
  • 查看es的数据卷挂载目录
docker volume inspect es-plugins
  • 显示结果
[
    {
        "CreatedAt": "2022-05-06T10:06:34+08:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/es-plugins/_data",
        "Name": "es-plugins",
        "Options": null,
        "Scope": "local"
    }
]
  • 把IK分词器的解压文件放入/var/lib/docker/volumes/es-plugins/_data中即可
  • 重启es
docker restart es

2.5.1 IK分词器的两种模式

  • ik_smart:最少切分
  • ik_max_word:最细切分

2.5.2 IK分词器的扩展词词典

  • 随着互联网的发展,“造词运动”也越发的频繁。出现了很多新的词语,在原有的词汇列表中并不存在。比如:“奥力给”,“绝绝子” 等。我们需要把一些新词扩展到IK分词器中

  • 打开IK分词器config目录

  • 在IKAnalyzer.cfg.xml配置文件内容添加:

  • 在这个目录下新建一个 ext.dic,可以参考config目录下复制一个配置文件进行修改,然后输入新词保存即可。

  • 重启elasticsearch

docker restart es

2.5.2 停用词词典

  • 与扩展词词典一样、config目录下默认有stopword.dic文件打开后把我们想停用的词输入 保存即可。
  • 重启elasticsearch
docker restart es

2.6 Mapping索引库操作

  • 索引库类似于数据库中的建表操作

2.6.1 常见mapping属性

type数据类型
type数据类型
index是否索引
analyzer分词器
properties子字段
type常见有哪些
字符串text,keyword
数字long/integet/short/byte/double/float
布尔boolean
日期date
对象object

2.6.2 创建索引库

  • ES中通过Restful请求操作索引库、文档。请求内容用DSL语句来表示。创建索引库和mapping的DSL语法如下:
PUT /索引库名称
{
  "mappings": {
    "properties": {
      "字段名":{
        "type": "text",
        "analyzer": "ik_smart"
      },
      "字段名2":{
        "type": "keyword",
        "index": "false"
      },
      "字段名3":{
        "properties": {
          "子字段": {
            "type": "keyword"
          }
        }
      },
      // ...略
    }
  }
}

2.6.3 查看、删除、更新索引库

  • 查询索引库
PUT /索引库名
  • 删除索引库
DELETE /索引库名
  • 更新索引库
#更新索引库 只能添加新字段,不能修改已有字段
PUT /索引库名/_mapping
{
  "properties": {
    "新字段名":{
      "type": "integer"
    }
  }
}

2.7 文档操作

  • 查看文档:GET /索引库名/_doc/文档id
  • 添加文档
POST /索引库名/_doc/文档id
{
    "字段1": "值1",
    "字段2": "值2",
    "字段3": {
        "子属性1": "值3",
        "子属性2": "值4"
    },
    // ...
}
  • 删除文档:DELETE /索引库名/_doc/文档id
  • 更新文档
    1.全量修改,会删除旧文档,添加新文档
PUT /索引库名/_doc/文档id
{
    "字段1": "值1",
    "字段2": "值2",
    // ... 略
}

2.增量修改,修改指定字段值

POST /索引库名/_update/文档id
{
    "doc": {
         "字段名": "新的值",
    }
}

2.8 RestClient操作客户端

2.8.1 通过java代码实现对elasticsearch的操作

  • pom依赖
引入es的RestHighLevelClient依赖:
<dependency>
  <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-high-level-client</artifactId>
</dependency>
  • 创建测试类初始化客户端
@BeforeEach//先运行这个方法进行绑定客户端
    void setUp(){
        this.client=new RestHighLevelClient(RestClient.builder(HttpHost.create("http://192.168.36.129:9200")));
    }

2.8.2 RestClient索引库的增删查

  • 公共部分
private RestHighLevelClient client;
  • 创建索引库
//创建索引库
    @Test
    void t2() throws IOException {
        //1. 创建索引库对象
        CreateIndexRequest request = new CreateIndexRequest("hotel");
        //2. 请求参数,HotelIndex.INDEX_MAPPING是创建索引库的字符串模板,内容是创建索引库的DSL语句
        request.source(HotelIndex.INDEX_MAPPING, XContentType.JSON);
        //3. 发送请求
        client.indices().create(request, RequestOptions.DEFAULT);
    }
  • 删除索引库
//删除索引库
    @Test
    void t3() throws IOException {
        //1.创建删除索引库请求对象
        DeleteIndexRequest request = new DeleteIndexRequest("hotel");
        //发送删除请求
        client.indices().delete(request,RequestOptions.DEFAULT);
    }
  • 查询索引库
//查询索引库是否存在
    @Test
    void t4() throws IOException {
        //1.创建查询索引库请求对象
        GetIndexRequest request = new GetIndexRequest("hotel");
        //发送请求
        boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
        System.out.println(exists==true?"索引库已经存在":"索引库不存在");
    }

2.8.3 RestClient文档的增删改查

  • 新增文档
//新增文档
    @Test
    void t5() throws IOException {
        Hotel data = hotelService.getById(61083L);
        HotelDoc hotelDoc = new HotelDoc(data);
        //1.准备Request对象
        IndexRequest request = new IndexRequest("hotel").id(hotelDoc.getId().toString());
        //2.准备JSON文档(索引库中的数据)
        request.source(JSON.toJSONString(hotelDoc),XContentType.JSON);
        //3.发送请求
        client.index(request,RequestOptions.DEFAULT);
    }
  • 删除文档
//删除文档
    @Test
    void t8() throws Exception{
        DeleteRequest request = new DeleteRequest("hotel","61083");
        client.delete(request,RequestOptions.DEFAULT);
    }
  • ````修改文档```
//更新文档
    @Test
    void t7() throws Exception{
        //1.准备Request
        UpdateRequest request = new UpdateRequest("hotel","61083");
        //2.准备请求参数
        request.doc(
                //部分更新 key value的形式
                "price","666",
                "name","李四"
        );
        client.update(request,RequestOptions.DEFAULT);
    }
  • 查询文档
//查询文档
    @Test
    void t6() throws IOException {
        //1.查询请求对象
        GetRequest request = new GetRequest("hotel","61083");
        //2.发送请求,得到文档响应数据
        GetResponse documentFields = client.get(request, RequestOptions.DEFAULT);
        //3.拿到文档数据中的source
        String data = documentFields.getSourceAsString();
        //4.将source反序列化为对象
        HotelDoc hotelDoc = JSON.parseObject(data, HotelDoc.class);
        System.out.println("文档数据===>"+hotelDoc);
    }
  • 批量新增
//批量新增
    @Test
    void t9() throws Exception{
        BulkRequest request = new BulkRequest();
        List<Hotel> lists = hotelService.list();
        for (Hotel list : lists) {
            HotelDoc hotelDoc = new HotelDoc(list);
            request.add(new IndexRequest("hotel").id(hotelDoc.getId().toString()).source(JSON.toJSONString(hotelDoc),XContentType.JSON));

        }
        client.bulk(request,RequestOptions.DEFAULT);
    }

2.9 DSL查询语法

  • 查询所有:查询出所有数据,一般测试用。例如:match_all
  • 全文检索(full text)查询:利用分词器对用户输入内容分词,然后去倒排索引库中匹配。例如:match_query 和 multi_match_query
  • 精确查询:根据精确词条值查找数据,一般是查找keyword、数值、日期、boolean等类型字段。例如:ids range term
  • 地理(geo)查询:根据经纬度查询。例如:geo_distance 和 geo_bounding_box

2.9.1 DSL Query基本语法

GET /indexName/_search
{
  "query": {
    "查询类型": {
      "查询条件": "条件值"
    }
  }
}
例:
GET /hotel/_search
{
  "query": {
    "match_all": {}
  }
}

2.9.2 DSL全文检索查询

  • 全文检索查询的一种,会对用户输入内容分词,然后去倒排索引库检索
GET /索引库/_search
{
  "query": {
    "match": {
      "FIELD": "TEXT"
    }
  }
}
例:
GET /hotel/_search
{
  "query": {
    "match": {
      "all": "外滩五钻"
    }
  }
}

  • 查询多个字段
GET /索引库/_search
{
  "query": {
    "multi_match": {
      "query": "TEXT",
      "fields": ["FIELD1", " FIELD12"]
    }
  }
}
  • match:根据一个字段查询
  • multi_match:根据多个字段查询,参与查询字段越多,查询性能越差

2.9.3 DSL精确查询

  • term精确查询
#精确查询
GET /hotel/_search
{
  "query": {
    "term": {
      "FIELD": {
        "value": "VALUE"
      }
    }
  }
}
例:
#精确查询
GET /hotel/_search
{
  "query": {
    "term": {
      "city": {
        "value": "上海"
      }
    }
  }
}
  • range范围查询
GET /hotel/_search
{
  "query": {
    "range": {
      "FILED": {
        "gte": value,
        "lte": value
      }
    }
  }
}
例:
GET /hotel/_search
{
  "query": {
    "range": {
      "price": {
        "gte": 100,
        "lte": 200
      }
    }
  }
}

2.9.4 DSL地理位置查询

  • 根据geo-distance位置范围查询
GET /hotel/_search
{
  "query": {
    "geo_distance":{
      # distance: 可以设定查询距离
      "distance":"2km",
      # location:当前地址位置,此字段必须是 geo_point类型
      "location":"31.21,121.5"
    }
  }
}

2.9.5 Function Score Query

  • 当我们对第一次的搜索排序进行人工干预时,就需要用到Function Score 函数 可以自定义结果,让排序的结果变成我们想要的解构。 比如进行排名,一些酒店掏钱了,那么我们就可以通过Function Score进行加权算分 让我们想要的结果变成真
  • 在原来查询的条件下进行加权算分
GET /hotel/_search
{
  "query": {
    "function_score": {
      #第一次进行条件查询匹配
      "query": {"match": {
        "all": "外滩"
      }},
      #算分函数
      "functions": [
        {
          "filter": {
            "term": {
              "brand": "如家"
            }
          },
          #算分权重为 10
          "weight": 10
        }
      ],
      #加权模式  boost_mode:乘法
      "boost_mode": "multiply"
    }
  }
}

2.9.6 Boolean Query

  • 布尔查询是一个或多个查询子句的组合。子查询的组合方式有:
  1. must:必须匹配每个子查询,类似“与”
  2. should:选择性匹配子查询,类似“或”
  3. must_not:必须不匹配,不参与算分,类似“非”
  4. filter:必须匹配,不参与算分
  • 演示
  • 需求:搜索名字包含“如家”,价格不高于400,在坐标31.21,121.5周围10km范围内的酒店。
GET /hotel/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
          "name": "如家"
          }
          
        }
      ],
      "must_not": [
        {
          "range": {
            "FIELD": {
              "lte": 500
            }
          }
        }
      ],
      "filter": [
        {
          "geo_distance": {
            "distance": "10km",
            "location": {
              "lat": 31.21,
              "lon": 121.5
            }
          }
        }
      ]
    }
  }
}

2.10 搜索结果处理

2.10.1 排序 sort

  • 语法
GET /索引库名称/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "FIELD": "desc"  // 排序字段和排序方式ASC、DESC
    }
  ]
}

2.10.2 分页 from size

  • 语法
GET /索引库名称/_search
{
  "query": {
    "match_all": {}
  },
  "from": 从第几条数据开始查询, // 分页开始的位置,默认为0
  "size": 显示查询几条, // 期望获取的文档总数
  "sort": [
    {"按照哪个字段排序": "asc"}
  ]
}

2.10.3 高亮处理

  • 语法:高亮处理,默认情况搜索字段必须与高亮字段保持一致
GET /索引库名称/_search
{
  "query": {
    "match": {
      "FIELD": "TEXT"
    }
  },
  "highlight": {
    "fields": { // 指定要高亮的字段
      "FIELD": {
        "require_field_match":"false" #搜索字段与高亮字段匹配为false
        "pre_tags": "<em>",  // 用来标记高亮字段的前置标签
        "post_tags": "</em>" // 用来标记高亮字段的后置标签
      }
    }
  }
}

2.10 RestClient 查询文档

2.10.1 快速入门查询文档

	@Test
    void t1() throws IOException {
        //1.创建搜索请求对象
        SearchRequest request = new SearchRequest("索引库名称");
        //2.准备DSL参数
        request.source().query(QueryBuilders.matchAllQuery()).from(0).size(10);
        //3.发送请求 得到数据集合
        SearchResponse search = client.search(request, RequestOptions.DEFAULT);
        //4.解析响应数据
        SearchHits hits = search.getHits();
        //拿到数据集合中Hits数据的条数
        long value = hits.getTotalHits().value;
        //拿到数据集合
        SearchHit[] hits1 = hits.getHits();
        //5.遍历数据
        for (SearchHit hit : hits1) {
            System.out.println(hit.getSourceAsString());
        }
    }

2.10.2 全文检索 单字段查询

	@Test
    void t2() throws IOException {
        //1.创建搜索请求对象
        SearchRequest request = new SearchRequest("索引库名");
        //2.准备DSL参数
        request.source().query(QueryBuilders.matchQuery("字段","值")).from(0).size(10);
        //3.发送请求 得到数据集合
        SearchResponse search = client.search(request, RequestOptions.DEFAULT);
        //4.解析响应数据
        SearchHits hits = search.getHits();
        //拿到数据集合中Hits数据的条数
        long value = hits.getTotalHits().value;
        //拿到数据集合
        SearchHit[] hits1 = hits.getHits();
        //5.遍历数据
        for (SearchHit hit : hits1) {
            System.out.println(hit.getSourceAsString());
        }
    }

2.10.3 全文检索 多字段查询

	@Test
    void t3() throws IOException {
        //1.创建搜索请求对象
        SearchRequest request = new SearchRequest("hotel");
        //2.准备DSL参数
        request.source().query(QueryBuilders.multiMatchQuery("查询的值","查询字段","查询字段",...)).from(0).size(10);
        //3.发送请求 得到数据集合
        SearchResponse search = client.search(request, RequestOptions.DEFAULT);
        //4.解析响应数据
        SearchHits hits = search.getHits();
        //拿到数据集合中Hits数据的条数
        long value = hits.getTotalHits().value;
        //拿到数据集合
        SearchHit[] hits1 = hits.getHits();
        //5.遍历数据
        for (SearchHit hit : hits1) {
            System.out.println(hit.getSourceAsString());
        }
    }

2.10.4 bool多条件查询

	@Test
    void t4() throws IOException {
        //1.创建搜索请求对象
        SearchRequest request = new SearchRequest("hotel");
        //2.准备DSL参数
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
        //精确查询
        boolQueryBuilder.must(QueryBuilders.termQuery("字段名","查询的值"));
        //范围查询
        boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").lte(300));
        request.source().query(boolQueryBuilder);
        //3.发送请求 得到数据集合
        SearchResponse search = client.search(request, RequestOptions.DEFAULT);
        //4.解析响应数据
        SearchHits hits = search.getHits();
        //拿到数据集合中Hits数据的条数
        long value = hits.getTotalHits().value;
        //拿到数据集合
        SearchHit[] hits1 = hits.getHits();
        //5.遍历数据
        for (SearchHit hit : hits1) {
            System.out.println(hit.getSourceAsString());
        }
    }

2.10.5 排序

	@Test
    void t5() throws Exception{
        //1.创建搜索请求对象
        SearchRequest request = new SearchRequest("索引库名");
        //2.准备DSL参数
        request.source().sort("price", SortOrder.以上是关于ElasticSearch保姆级入门教程的主要内容,如果未能解决你的问题,请参考以下文章

Linux 集群 Elasticsearch保姆级教程

Elasticsearch下载配置(保姆级教学)

Elasticsearch下载配置(保姆级教学)

Elasticsearch下载配置(保姆级教学)

深度学习保姆级教程(附代码+数据)

深度学习保姆级教程(附代码+数据)