ElasticSearch

ElasticSearch

仿京东搜索Gitee地址:https://gitee.com/infiniteStars/elastic-search-jd

1.简介

  • Elasticsearch是一个基于==Lucene==的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。

  • Elasticsearch 是一个分布式、高扩展、高实时搜索数据分析引擎。

  • 它能很方便的使大量数据具有搜索、分析和探索的能力。

  • Elasticsearch 的实现原理主要分为以下几个步骤,首先用户将数据提交到Elasticsearch 数据库中,再通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据,当用户搜索数据时候,再根据权重将结果排名,打分,再将返回结果呈现给用户。

2.安装

下载地址:https://www.elastic.co/cn/downloads/elasticsearch

  1. 下载后解压即可。
  2. 如果在bin目录下,双击elasticsearch.bat 闪退的话,可以打开命令提示符(管理员模式),到bin目录。输入elasticsearch.bat。

这样可以看到是哪里出错的,以便进行修改。

  1. 启动成功后,会出现以下界面。

image-20210530170217298

  1. 访问进行

image-20210530170248464

安装可视化界面 head插件

  1. 下载地址 https://github.com/mobz/elasticsearch-head

  2. 解压后,通过命令行进入该目录。

  3. cnpm install   #安装依赖
    npm run strat    #启动
    

    image-20210530171615585

  4. 访问

image-20210530171642668

  1. 点击连接没有反应,因为跨域了。所以要进行配置。
  2. 进入 elasticsearch-7.13.0\config\elasticsearch.yml 目录,在下边添加以下代码
http.cors.enabled: true
http.cors.allow-origin: "*"
  1. 刷新http://localhost:9100/

image-20210530174546797

3.Kibana

1.简介

  • Kibana是一个开源的分析与可视化平台,设计出来用于和Elasticsearch一起使用的。可以用kibana搜索、查看存放在Elasticsearch中的数据。Kibana与Elasticsearch的交互方式是各种不同的图表、表格、地图等,直观的展示数据,从而达到高级的数据分析与可视化的目的。
  • Elasticsearch、Logstash和Kibana这三个技术就是我们常说的ELK技术栈,可以说这三个技术的组合是大数据领域中一个很巧妙的设计。一种很典型的MVC思想,模型持久层,视图层和控制层。Logstash担任控制层的角色,负责搜集和过滤数据。Elasticsearch担任数据持久层的角色,负责储存数据。而Kibana担任视图层角色,拥有各种维度的查询和分析,并使用图形化的界面展示存放在Elasticsearch中的数据。

2.安装

  • 版本要和El对应asticSearch
  1. 下载地址 https://www.elastic.co/cn/downloads/kibana
  2. 解压,点击bin目录下的 kibana.bat 启动。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HbhofHJh-1631692190556)(C:\Users\86155\AppData\Roaming\Typora\typora-user-images\image-20210530190711883.png)]

  1. 访问 http://localhost:5601

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-35dWPWg2-1631692190557)(C:\Users\86155\AppData\Roaming\Typora\typora-user-images\image-20210530190757191.png)]

  1. 可以看到页面是英文的,可以设置成中文。

    到config目录下的 kibana.yml,进行编辑。在最后一行添加

    i18n.locale: "zh-CN"
    
  2. 重新启动服务,可以看到已经汉化了。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-71QaQJ32-1631692190558)(C:\Users\86155\AppData\Roaming\Typora\typora-user-images\image-20210530191347220.png)]

4.核心概念

ElasticSearch是面向文档的,接下来用关系型数据库对ES中的概念进行理解。

ElasticSearchDB(关系型数据库)
索引(indices)数据库(datebase)
types表(table)
documents(文档)行(rows)
fields字段(columns)

5.Ik分词器

  • IK体用了两个分词算法:ik_smart和ik_max_word, ik_smart为最少切分 , ik_max_word为最细粒度划分!
  1. 下载 https://github.com/medcl/elasticsearch-analysis-ik
  2. 注意:下载第一个,否则启动的时候会报错。

image-20210531192721663

  1. 解压完成后,放在 D:\Environment\ElasticSearch\elasticsearch-7.13.0\plugins 目录下即可。
  2. 启动elasticsearch
  3. 启动kibana测试

查看不同的分词效果

ik_smart

image-20210531193840496

ik_max_word(将词的排列组合都列举出来)

image-20210531193931979

  • 有时候我们自定义的词,它拆分不出来。如果想让它完整显示出来,需要我们进行配置。

  • elasticsearch-7.13.0\plugins\ik\config 在这个目录下新建一个 XXX.dic 文件,将想要词写进去。

  • 在 IKAnalyzer.cfg.xml 进行配置。

image-20210531194738953

  • 重启服务,可以发现能拆分成我们想要的词。

6.Restful风格操作

含义

  • 一种软件架构风格,而不是标准,只是提供了一组设计原则和约束条件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制.

基本Rest风格命令说明

methodurl地址描述
PUT127.0.01:9200/索引名称/类型名称/文档id创建文档(指定id)
POST127.0.01:9200/索引名称/类型名称创建文档(随机id)
POST127.0.01:9200/索引名称/类型名称/文档id/_update修改文档
POST127.0.01:9200/索引名称/类型名称/文档id/_search查询所有数据
GET127.0.01:9200/索引名称/类型名称/文档id通过文档id查询文档
DELETE127.0.01:9200/索引名称/类型名称/文档id删除文档

1.创建数据

image-20210531200622802

image-20210531200708710

  • 创建索引规则
PUT /test2
{
  "mappings": {
    "properties": {
      "name": {
        "type": "text"
      },
      "age": {
        "type": "integer"
      },
      "birthday": {
        "type": "date"
      }
    }
  }
}

image-20210531201819368

2.获取数据

GET test1/test1/1
GET test2   # 可以查看默认类型
GET test1/test1/_search?q=name: dz   #条件查询

image-20210531202156772

  • 通过 GET _cat/indices 这个命令查看所有索引的信息。

image-20210531202857023

3.修改数据

1.第一种方法

在 put 创建的地方直接修改数据。

2.第二种方法
POST /test1/test1/1/_update
{
  "doc": {
    "name": "yzc"
  }
}

image-20210531203547212

4.删除数据

DELETE test1

7.高级查询(重点)

GET test1/test1/_search
{
  "query": {
    "match": {
      "name": "dz"
    }
  },
  "_source": ["name","age"],   #结果过滤,列过滤
  "sort": {
    "age": {                    #按年龄进行降序查询
      "order": "desc"
    }
  },
  "from": 0,     #分页查询   从第几个数据开始,显示几条数据  单页查询
  "size": 1
}

image-20210531210002838

多条件查询

GET test1/test1/_search
{
  "query": {
    "bool": {
      "must": [    #must  下边所有的条件都要符合 相当于and
        {
          "match": {       #匹配
            "name": "dz"
          }
        },
        {
          "match": {
            "age": "18"
          }
        }
      ]
    }
  }
}
--------------------------------------------------

GET test1/test1/_search
{
  "query": {
    "bool": {
      "should": [   #匹配一个即可  相当于 or
        {
          "match": {
            "name": "dz"
          }
        },
        {
          "match": {
            "age": "18"
          }
        }
      ]
    }
  }
}
--------------------------------
GET test1/test1/_search
{
  "query": {
    "bool": {
      "must_not": [    #相当于 not 
        {
          "match": {
            "name": "dz"
          }
        }
      ]
    }
  }
}
-----------------------------------
GET test1/test1/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "name": "dz"
          }
        }
      ],
      "filter": {    #对查询出来的数据进行过滤
        "range": {
          "age": {
            "lt": 10
          }
        }
      }
    }
  }
}
  • gt (greater than) 大于
  • gte(greater than equals) 大于等于
  • lt (less than) 小于
  • lte (less than equals) 小于等于

keyword 和 text的区别

使用 term 进行精确查询的时候,keyword 不会被分词器解析,而 text 会被分词器解析。

高亮显示

GET test1/test1/_search
{
  "query": {
    "match": {
      "name": "dz"
    }
  },
  "highlight": {
    "fields": {
      "name": {}   #name 设置高亮
    }
  }
}

8.集成SpringBoot

  • 学习文档 https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high-compatibility.html

1.创建项目

  1. 新建一个SpringBoot项目
  2. 勾选 nosql中的 ElasticSearch。
  3. 在pom.xml中修改ElasticSearch版本
 <properties>
     <java.version>11</java.version>
     <elasticsearch.version>7.13.0</elasticsearch.version>
</properties>
  1. 编写配置类
@Configuration
public class ElasticSearchClientConfig {

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

2.操作索引

1.创建索引
@Qualifier("restHighLevelClient")
@Autowired
private RestHighLevelClient client;
//创建索引
@Test
void createIndex() throws IOException {
    //创建索引请求
    CreateIndexRequest request = new CreateIndexRequest("dz");
    //客户端执行请求
    CreateIndexResponse response = client.indices().create(request, RequestOptions.DEFAULT);
    System.out.println(response);
}
2.判断索引是否存在
 //判断索引是否存在
@Test
void existsIndex() throws IOException {
    //创建索引请求
    GetIndexRequest request = new GetIndexRequest("dz");
    //客户端执行请求
    boolean response = client.indices().exists(request, RequestOptions.DEFAULT);
    System.out.println(response);
}
3.删除索引
//删除索引
@Test
void deleteIndex() throws IOException {
    //创建索引请求
    DeleteIndexRequest delete = new DeleteIndexRequest("dz");
    AcknowledgedResponse response1 = client.indices().delete(delete, RequestOptions.DEFAULT);
    System.out.println(response1.isAcknowledged());
}

3.操作数据

1.插入数据
 //向索引插入数据
@Test
void testAdd() throws IOException {
    User user = new User("dz", 18);
    IndexRequest request = new IndexRequest("dz");
    request.id("1");
    //将数据放入请求
    request.source(JSON.toJSONString(user), XContentType.JSON);
    IndexResponse index = client.index(request, RequestOptions.DEFAULT);
    System.out.println(index.status());
}
2.获取数据
//获取数据
@Test
void getTest() throws IOException {
    GetRequest request = new GetRequest("dz","1");
    //判断数据是否存在
    boolean exists = client.exists(request, RequestOptions.DEFAULT);
    GetResponse fields = client.get(request, RequestOptions.DEFAULT);
    System.out.println(fields.getSourceAsString());
}
3.更新数据
//更新数据
@Test
void updateTest() throws IOException {
UpdateRequest request = new UpdateRequest("dz", "1");
User user = new User("zsq", 18);
request.doc(JSON.toJSONString(user),XContentType.JSON);
UpdateResponse update = client.update(request, RequestOptions.DEFAULT);
System.out.println(update.status());
}
4.删除数据
 //删除数据
@Test
void deleteTest() throws IOException {
    DeleteRequest request = new DeleteRequest("dz", "1");
    request.timeout("1s");
    DeleteResponse delete = client.delete(request, RequestOptions.DEFAULT);
    System.out.println(delete.status());
}
5.批量插入数据
  • 其他操作同理
 //批量插入数据
@Test
void BulkInsertTest() throws IOException {
    BulkRequest request = new BulkRequest();
    request.timeout("10s");
    ArrayList<User> users = new ArrayList<>();
    users.add(new User("dz1",18));
    users.add(new User("dz2",18));
    users.add(new User("dz3",18));
    users.add(new User("dz4",18));
    users.add(new User("dz5",18));
    for (int i = 0; i < users.size(); i++) {
        request.add(
            new IndexRequest("dz").id(""+i+1).source(JSON.toJSONString(users.get(i)),XContentType.JSON));
    }
    BulkResponse bulk = client.bulk(request, RequestOptions.DEFAULT);
    System.out.println(bulk.hasFailures());
}
6.搜索数据(重点)
//查询
@Test
void SearchTest() throws IOException {
    //搜索哪一个索引
    SearchRequest request = new SearchRequest("dz");
    //构建搜索条件
    SearchSourceBuilder builder = new SearchSourceBuilder();
    //精准查询,name为实体类的属性
    TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("name", "dz1");
    //匹配所有
    MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();

    builder.query(termQueryBuilder);
    request.source(builder);
    SearchResponse search = client.search(request, RequestOptions.DEFAULT);
    SearchHits hits = search.getHits();
    System.out.println(JSON.toJSONString(hits));
}

4.高亮搜索(重点)

将数据库中的数据放在创建的索引中

//将数据库里面的数据添加到es的index中,这个操作应该在service层中实现
public void addes() throws IOException {
    //获取数据
    List<Book> books = bookService.list();
    //批量存放
    BulkRequest bulkRequest = new BulkRequest();
    bulkRequest.timeout("2m");
    for (int i = 0; i < books.size(); i++) { 
        bulkRequest.add(new IndexRequest("books")   //创建索引
                        .source(JSON.toJSONString(books.get(i)), XContentType.JSON));
    }
    BulkResponse bulk = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
    System.out.println(!bulk.hasFailures());
}

执行搜索

//条件搜索
public List<Map<String,Object>> searchPage(String keyword, int pageNo, int pageSize) throws IOException {
    if (pageNo < 1)
        pageNo = 1;
    //条件搜索   搜索books索引里的内容
    SearchRequest searchRequest = new SearchRequest("books");
    //构建搜索条件
    SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

    //分页
    sourceBuilder.from(pageNo);
    sourceBuilder.size(pageSize);

    //精准匹配   如果name属性中含有keyword,则会高亮显示
    TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("name", keyword);
    sourceBuilder.query(termQueryBuilder);
    //超时设置
    sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));

    //高亮
    HighlightBuilder highlightBuilder = new HighlightBuilder();
    //高亮字段
    highlightBuilder.field("name");
    //如果name里面有多个keyword,则只显示第一个
    highlightBuilder.requireFieldMatch(false); //关闭多个高亮显示,只显示第一个
    //自定义如何高亮
    highlightBuilder.preTags("<span style='color:red'>");
    highlightBuilder.postTags("</span>");
    sourceBuilder.highlighter(highlightBuilder);

    //执行搜索
    searchRequest.source(sourceBuilder);
    //搜索的结果
    SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
    //解析结果
    List<Map<String, Object>> list = new ArrayList<>();
    for (SearchHit hit : searchResponse.getHits().getHits()) {
        //获取所有的高亮字段
        Map<String, HighlightField> highlightFields = hit.getHighlightFields();
        HighlightField title = highlightFields.get("name");
        Map<String, Object> sourceAsMap = hit.getSourceAsMap(); //原来的字段,
        //解析高亮的字段,将原来的字段替换为高亮的字段
        if (title != null){
            //高亮字段
            Text[] fragments = title.fragments();
            String n_title = "";
            for (Text text : fragments) {
                n_title += text;
            }
            sourceAsMap.put("name",n_title); //执行替换
        }
        list.add(hit.getSourceAsMap());
    }
    return list;
}
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值