ElasticSearch入门

ElasticSearch

Elasticsearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java语言开发的,并作为Apache许可条款下的开放源码发布,是一种流行的企业级搜索引擎。Elasticsearch用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。官方客户端在Java、.NET(C#)、PHP、Python、Apache Groovy、Ruby和许多其他语言中都是可用的。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr,也是基于Lucene。

ES目录结构

bin	启动文件
config	配置文件
	log4j2	日志配置文件
	jvm.options java虚拟机相关配置
	elasticsearch.yml	elasticsearch配置文件 默认9200端口
lib	相关jar包
logs	日志
modules	功能模块
plugins	插件

Docker下安装

默认端口: 9200 , 9300, kibana连接端口: 5601

docker run -it -e "discovery.type=single-node" --name elasticsearch -d -p 9200:9200 -p 9300:9300 -p 5601:5601 elasticsearch

在docker下安装需要映射以上两个端口, 启动后可通过浏览器访问, 出现以下信息则说明启动成功

{
  "name" : "0F6pJCO",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "Ra_qBBOnQumXsBrpN5nMrQ",
  "version" : {
    "number" : "5.6.12",
    "build_hash" : "cfe3d9f",
    "build_date" : "2018-09-10T20:12:43.732Z",
    "build_snapshot" : false,
    "lucene_version" : "6.6.1"
  },
  "tagline" : "You Know, for Search"
}

ELK

"ELK"是三个开源项目的首字母缩写,这三个项目分别是:Elasticsearch、Logstash 和 Kibana。Elasticsearch 是一个搜索和分析引擎。Logstash 是服务器端数据处理管道,能够同时从多个来源采集数据,转换数据,然后将数据发送到诸如 Elasticsearch 等“存储库”中。Kibana 则可以让用户在 Elasticsearch 中使用图形和图表对数据进行可视化

Elastic Stack 是 ELK Stack 的更新换代产品。

安装Kibana

Kibana版本需要和ES版本一致

默认端口:5601

可通过浏览器访问, 进入默认界面则启动成功

docker run -it -d -e ELASTICSEARCH_URL=http://127.0.0.1:9200 --name kibana --network=container:elasticsearch kibana

ES核心概念

ES是面向文档, 数据以JSON形式存储

关系型数据库和ES的对比

Relationl DBElasticsearch
数据库(database)索引(indices)
表(tables)types
行(rows)documents
字段(columns)fields

IK分词器

IK Analyzer是一个开源的,基于java语言开发的轻量级的中文分词工具包。。最初,它是以开源项目Luence为应用主体的,结合词典分词和文法分析算法的中文分词组件。

安装参考:https://www.cnblogs.com/szwdun/p/10664348.html

分词效果

ik_smart为最小切分

GET _analyze
{
  "analyzer": "ik_smart",
  "text": "中华人民共和国"
}

//结果
{
  "tokens" : [
    {
      "token" : "中华人民共和国",
      "start_offset" : 0,
      "end_offset" : 7,
      "type" : "CN_WORD",
      "position" : 0
    }
  ]
}

ik_max_word为最细密度切分

GET _analyze
{
  "analyzer": "ik_max_word",
  "text": "中华人民共和国"
}

//结果
{
  "tokens" : [
    {
      "token" : "中华人民共和国",
      "start_offset" : 0,
      "end_offset" : 7,
      "type" : "CN_WORD",
      "position" : 0
    },
    {
      "token" : "中华人民",
      "start_offset" : 0,
      "end_offset" : 4,
      "type" : "CN_WORD",
      "position" : 1
    },
      
    ...
      
  ]
}

自定义分词

在es的/plugin/ik/config/目录下添加自己的dic词典文件

IKAnalyzer.cfg.xml中添加自己的配置

重启ES生效


Rest风格说明

一种软件架构风格, 只是提供了一组设计原则和约束条件. 它主要用于客户端和服务器交互类的软件. 基于这个风格设计的软件可以更简介, 更有层次, 更易于实现缓存等机制.

基本Rest命令说明

methodurl地址描述
PUTlocalhost:9200/索引名称/类型名称/文档id创建文档(指定文档id)
POSTlocalhost:9200/索引名称/类型名称创建文档(随机文档id)
POSTlocalhost:9200/索引名称/类型名称/文档id/_update修改文档
DELETElocalhost:9200/索引名称/类型名称/文档id删除文档
GETlocalhost:9200/索引名称/类型名称/文档id通过id查询文档
POSTlocalhost:9200/索引名称/类型名称/_search查询所有数据

基本类型说明

类型关键字
字符串类型text, keyword
数值类型long, integer, short, byte, double, float, half_float, scaled_folat
日期类型date
布尔类型boolean
二进制类型binary

创建索引并指定类型

PUT /test2
{
  "mappings": { //映射
    "properties": {
      "name": {	//字段
        "type": "text" //类型
      },
      "age": {
        "type": "integer"
      },
      "birthday": {
        "type": "date"
      }
    }
  }
}

结果:

{
  "acknowledged" : true,
  "shards_acknowledged" : true,
  "index" : "test2"
}

基础测试

  1. 创建一个索引

    PUT /test1/type1/1
    {
      "name": "乔布斯",
      "age": "50"
    }
    

    结果:

    {
      "_index" : "test1",	//索引
      "_type" : "type1", //类型
      "_id" : "1",	//id
      "_version" : 1, //版本
      "result" : "created",	//操作
      "_shards" : {
        "total" : 2,	//索引中文档数
        "successful" : 1,	//是否成功
        "failed" : 0
      },
      "_seq_no" : 1,
      "_primary_term" : 1
    }
    
  2. 获取es当前信息 GET _cat

  3. 修改数据

    doc中指定需要修改的数据

    POST /test2/_doc/1/_update
    {
      "doc": {
        "name": "root"
      }
    }
    
  4. 删除数据

    DELETE /test1
    
  5. 查询数据

    查询索引中所有的文档

    POST /blog/user/_search
    
    复杂查询: 使用json构建
    GET /blog/user/_search
    {
      "query": { //查询
        "match": { //匹配
          "name": "root"
        }
      },
        
      "_source":["name","desc"], //显示部分属性(结果过滤)
        
      "sort":{	//排序
          "age": {
            "order": "desc" //升序(asc,降序)
          }
        },
        //分页
      "from": 0, //开始数据
      "size": 2	//每页大小
    }
    

    精确查询

    must中所有条件都要符合(and)

    should中满足其一(or)

    must_not反选(not)

    GET /blog/user/_search
    {
      "query": {
        "bool": {
          "must": [ //must中所有条件都要符合(and)
            {
              "match": {
                "name": "root"
              }
            },
            {
              "match": {
                "age": 23
              }
            }
          ]
        }
      }
    }
    

    过滤器
    GET /blog/user/_search
    {
      "query": {
        "bool": {
          "filter": [
            {
              "range": { 
                "age": {
                  "gt": 20 //大于
                  "gte": 20, //大于等于
                  "lte": 23 //小于等于
                  "lt": 23	//小于
                }
              }
            }
          ]
        }
      }
    }
    

    精确查找

    使用trem查询

    GET /blog/user/_search
    {
      "query": {
        "bool": {
          "should": [
            {
              "term": {
                "name": "root"
              }
            }
          ]
        }
      }
    }
    

    高亮查询
    GET /blog/user/_search
    {
      "query": {
        "match": {
          "desc": "测试"
        }
      },
      "highlight": {
        "pre_tags": "<small style='color:red'>", // 自定义前缀
        "post_tags": "</small>", // 自定义后缀
        "fields": {
          "desc": {}
        }
      }
    }
    

    结果:

    "hits" : [
          {
            "_index" : "blog",
            "_type" : "user",
            "_id" : "4",
            "_score" : 0.98433626,
            "_source" : {
              "name" : "roo_test",
              "age" : 20,
              "desc" : "root的测试用户",
              "tags" : [
                "哈哈哈",
                "hello",
                "world"
              ]
            },
            "highlight" : {
              "desc" : [
                "root的<small style='color:red'>测</small><small style='color:red'>试</small>用户"
              ]
            }
          },
        ...
    

集成SpringBoot

依赖坐标

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>

注意: restClient需和本地es版本保持一致

<!-- 自定义es版本依赖 保证和本地版本一致 -->
<elasticsearch.version>7.9.2</elasticsearch.version>

配置类

使用高版本rest客户端

@Configuration
public class ElasticSearchConfig {

    @Bean
    public RestHighLevelClient restHighLevelClient(){
        return new RestHighLevelClient(
                RestClient.builder(new HttpHost("192.168.154.128", 9200, "http")));
    }
}

关于索引

创建索引
/**
 * 创建索引
 */
@Test
public void createIndex() throws IOException {
   //创建索引请求
   CreateIndexRequest indexRequest = new CreateIndexRequest("blog");
   //执行请求 -> 获得响应
   CreateIndexResponse createIndexResponse = restHighLevelClient.indices().create(indexRequest, RequestOptions.DEFAULT);
   System.out.println(createIndexResponse.isAcknowledged());
}
判断索引存在
/**
 * 获取索引
 * 判断索引是否存在
 */
@Test
public void existIndex() throws IOException {
   //创建获取索引请求
   GetIndexRequest getIndexRequest = new GetIndexRequest("blog");
   //执行请求 -> 返回boolean值
   boolean exists = restHighLevelClient.indices().exists(getIndexRequest, RequestOptions.DEFAULT);
   System.out.println(exists);
}
删除索引
/**
 * 删除索引
 */
@Test
public void deleteIndex() throws IOException {
   //创建删除索引请求
   DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest("blog");
   //执行请求
   AcknowledgedResponse response = restHighLevelClient.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT);
   System.out.println(response.isAcknowledged());
}

关于文档

添加文档
/**
 * 添加文档
 */
@Test
public void createDocument() throws IOException {
   //创建对象
   UserInfo userInfo = new UserInfo("harlan", 23);
   //创建索引请求
   IndexRequest indexRequest = new IndexRequest("blog");
   //设置规则
   indexRequest.id("1");
   indexRequest.timeout(TimeValue.timeValueSeconds(1));
   indexRequest.timeout("1s");
   //将数据放入请求中 json
   indexRequest.source(JSON.toJSONString(userInfo), XContentType.JSON);
   //客户端发送请求, 获取响应结果
   IndexResponse response = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
   System.out.println(response.status());
}
判断文档存在
/**
 * 判断文档是否存在
 */
@Test
public void isExists() throws IOException {
   GetRequest getRequest = new GetRequest("blog", "1");
   boolean exists = restHighLevelClient.exists(getRequest, RequestOptions.DEFAULT);
   System.out.println(exists);
}
获取文档信息
/**
 *获取文档
 */
@Test
public void getDocument() throws IOException {
   GetRequest getRequest = new GetRequest("blog", "1");
   GetResponse response = restHighLevelClient.get(getRequest, RequestOptions.DEFAULT);
   System.out.println(response.getSourceAsString());
}
更新文档信息
/**
 * 更新文档
 */
@Test
public void updateDocument() throws IOException {
   UpdateRequest updateRequest = new UpdateRequest("blog", "1");
   updateRequest.timeout("1s");
   UserInfo userInfo = new UserInfo("root", 20);
   updateRequest.doc(JSON.toJSON(userInfo), XContentType.JSON);
   UpdateResponse response = restHighLevelClient.update(updateRequest, RequestOptions.DEFAULT);
   System.out.println(response.status());
}
删除文档
/**
 * 删除文档
 */
@Test
public void deleteDocument() throws IOException {
   DeleteRequest deleteRequest = new DeleteRequest("blog", "1");
   DeleteResponse response = restHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);
   System.out.println(response.status());
}
批量操作
/**
 * 批量操作
 */
@Test
public void bulkRequest() throws IOException {
   BulkRequest bulkRequest = new BulkRequest();
   bulkRequest.timeout("10s");
   List<UserInfo> userInfoList = new ArrayList<>();
   userInfoList.add(new UserInfo("harlan", 20));
   userInfoList.add(new UserInfo("PenXiaoC",26));
   userInfoList.add(new UserInfo("HuangBingY", 23));
   userInfoList.add(new UserInfo("ChengXiaoL", 22));

   //批处理请求
   for (int i = 0; i < userInfoList.size(); i++) {
      bulkRequest.add(new IndexRequest("blog")
            .id(""+(i+1)).source(JSON.toJSONString(userInfoList.get(i)), XContentType.JSON));
   }
   //执行请求
   BulkResponse responses = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
   System.out.println(responses.status());

}
搜索
/**
 * 搜索
 */
@Test
void search() throws IOException {
   SearchRequest searchRequest = new SearchRequest("blog");
   //构建查询
   SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
   //构建条件
   TermQueryBuilder termQuery = QueryBuilders.termQuery("name", "harlan");
   //放入查询构建
   sourceBuilder.query(termQuery);
   sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
   //分页
   sourceBuilder.from(0);
   sourceBuilder.size(1);
   //放入请求
   searchRequest.source(sourceBuilder);
   //执行请求
   SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
   //获取内容
   for (SearchHit hit : response.getHits().getHits()) {
      System.out.println(hit.getSourceAsMap());
   }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值