ElasticSearch 实现分词全文检索 - Scroll 深分页

elasticsearch,实现,分词,全文检索,scroll,分页 · 浏览次数 : 129

小编点评

**ElasticSearch 实现分词全文检索** **简介** ElasticSearch 是一个开源搜索引擎,它可以用于存储和搜索文本数据。由于其快速且高效的索引和搜索功能,ElasticSearch非常适合进行分词全文检索。 **安装和配置** 1. 安装 Elasticsearch:`npm install elasticsearch` 2. 创建一个索引: ```json { "index": "sms-logs-index", "type": "text", "settings": { "analysis.tokenizer": "standard" } } ``` **RESTful基本操作** 1. 获取搜索结果: ```json POST /_search ``` 2. 指定查询条件: ```json { "query": { "match_all": {} } } ``` 3. 设置分页参数: ```json { "size": 2, "sort": [ { "fee": { "order": "desc" } } ] } ``` **Java SpringBoot ES 索引操作** ```java @PostMapping("/_search") public ResponseEntity search(@RequestBody SearchRequest request) throws Exception { // 创建搜索请求 SearchResponse response = client.search(request, RequestOptions.DEFAULT); // 获取搜索结果 String scrollId = response.getScrollId(); // 打印结果 return ResponseEntity.ok("Results retrieved successfully").body(); } ``` **Java SpringBoot ES 文档操作** ```java @GetMapping("/_search/docs") public ResponseEntity getDocs(@RequestParam String scrollId) throws Exception { // 获取 ScrollId SearchScrollRequest scrollRequest = new SearchScrollRequest(scrollId); // 执行查询获取结果 SearchResponse scrollResponse = client.scroll(scrollRequest, RequestOptions.DEFAULT); // 打印结果 return ResponseEntity.ok("Results retrieved successfully").body(); } ``` **测试数据准备** ```json { "query": { "match_all": {} } } ``` **term、terms查询** ```json { "query": { "match": "term" } } { "query": { "match_all": {} } } ``` **id、ids、prefix、fuzzy、wildcard、range、regexp 查询** ```json { "query": { "match": "id" } } { "query": { "match": "ids" } } { "query": { "match": "prefix" } } { "query": { "match": "fuzzy" } } { "query": { "match": "wildcard" } } { "query": { "match": "range" } } { "query": { "match": "regexp" } } ``` **归纳** 使用 Elasticsearch 进行分词全文检索需要一些步骤,但它非常易于实现。通过使用 RESTful API 或 Java API,您可以轻松地管理索引和搜索。

正文

目录

ElasticSearch 实现分词全文检索 - 概述
ElasticSearch 实现分词全文检索 - ES、Kibana、IK安装
ElasticSearch 实现分词全文检索 - Restful基本操作
ElasticSearch 实现分词全文检索 - Java SpringBoot ES 索引操作
ElasticSearch 实现分词全文检索 - Java SpringBoot ES 文档操作
ElasticSearch 实现分词全文检索 - 测试数据准备
ElasticSearch 实现分词全文检索 - term、terms查询
ElasticSearch 实现分词全文检索 - match、match_all、multimatch查询
ElasticSearch 实现分词全文检索 - id、ids、prefix、fuzzy、wildcard、range、regexp 查询
ElasticSearch 实现分词全文检索 - Scroll 深分页
ElasticSearch 实现分词全文检索 - delete-by-query
ElasticSearch 实现分词全文检索 - 复合查询
ElasticSearch 实现分词全文检索 - filter查询
ElasticSearch 实现分词全文检索 - 高亮查询
ElasticSearch 实现分词全文检索 - 聚合查询 cardinality
ElasticSearch 实现分词全文检索 - 经纬度查询
ElasticSearch 实现分词全文检索 - 搜素关键字自动补全(suggest)
ElasticSearch 实现分词全文检索 - SpringBoot 完整实现 Demo 附源码

数据准备

ElasticSearch 实现分词全文检索 - 测试数据准备

深分页 Scroll

ES 对 from + size 有限制,两者之和不能超过1W
from + size 在 ES 查询数据的方式:

  • 第一步:将用户指定的关键词进行分词
  • 第二步:将词汇去词库中进行检索,得到多个文档id
  • 第三步:去各个分片中拉取指定的数据【耗时较长】
  • 第四步:根据score(匹配度)将数据进行排序,【耗时较长】
  • 第五步:根据 from 的值,将查询到的数据舍弃一部分
  • 第六步:返回结果

Scroll + size 在 ES 查询数据的方式:

  • 第一步:将用户指定的关键词进行分词
  • 第二步:将词汇去分词库中进行检索,得到多个文档的id
  • 第三步:将文档的id存放在一个ES的上下文中(设定保存时间,过期后移除)
  • 第四步:根据你指定的Size的个数去ES中检索指定个数的数据,拿到数据的文档id,会从上下文中移除
  • 第五步:如果需要下一页数据,直接去ES的上下文中找后续的内容
  • 第六步:循环第四步和第五步

Scroll查询方式,不适合做实时的查询,类似数据库中的游标,每次都是从数据文档中的ID去获取,效果高了,但文档中的ID(第二步)不是实时更新的,一般后台管理的方式用 Scroll 比较方便

Scroll不适合支持那种实时的和用户交互的前端分页工作,其主要用途用于从ES集群分批拉取大量结果集的情况,一般都是offline的应用场景。 比如需要将非常大的结果集拉取出来,存放到其他系统处理,或者需要做大索引的reindex等等。

# scroll 查询,返回第一页数据,并且将文档id信息存放在ES上下文中,指定生存时间 1m
POST /sms-logs-index/_search?scroll=1m
{
  "query": {
    "match_all": {}
    },
    "size": 2,
    "sort": [
      {
        "fee": {  # 指定排序
          "order": "desc"
        }
      }
    ]
  }
}

# 根据scroll查询下一页数据,【第一步设置了1分钟,所以1分钟以后再执行就没有数据了】
POST /_search/scroll
{
  "scroll_id":"FGluY2x1ZGVfY29udGV4dF91dWlkDXF1ZXJ5QW5kRmV0Y2gBFEQ1VkNuSVlCR2xMYVQ1OExzNU1tAAAAAAADNlcWMEt3d2xrY3hRWGFoZFlwM01ZdnlCdw==",  #根据上一步查的结果提到scroll_id
  "scroll":"1m" #生存时间
}

# 删除scroll在ES上下文中的数据
DELETE /_search/scroll/FGluY2x1ZGVfY29udGV4dF91dWlkDXF1ZXJ5QW5kRmV0Y2gBFEQ1VkNuSVlCR2xMYVQ1OExzNU1tAAAAAAADNlcWMEt3d2xrY3hRWGFoZFlwM01ZdnlCdw==

Java

@Test
void scrollQuery() throws Exception {
    String indexName = "sms-logs-index";
    RestHighLevelClient client = ESClient.getClient();

    //1. 创建SearchRequest对象
    SearchRequest request = new SearchRequest(indexName);

    //2. 指定scroll信息
    request.scroll(TimeValue.timeValueMinutes(2L)); //1分钟过期

    //2. 指定查询条件
    SearchSourceBuilder builder = new SearchSourceBuilder();
    builder.size(4);
    builder.sort("fee", SortOrder.DESC);
    builder.query(QueryBuilders.matchAllQuery());
    request.source(builder);

    //4. 获取返回结果 scrollid,source
    SearchResponse resp = client.search(request, RequestOptions.DEFAULT);
    String scrollId = resp.getScrollId();
    System.out.println("-------首页----------");
    for (SearchHit hit : resp.getHits().getHits()) {
        System.out.println(hit.getSourceAsMap());
    }
    while (true) {
        System.out.println("ScrollId =>" + scrollId);
        //5. 循环 - 创建SearchScrollRequest
        SearchScrollRequest scrollRequest = new SearchScrollRequest(scrollId);

        //6. 指定 ScrollId
        scrollRequest.scroll(TimeValue.timeValueMinutes(1L));

        //7. 执行查询获取返回结果
        SearchResponse scrollResp = client.scroll(scrollRequest, RequestOptions.DEFAULT);

        //8. 判断是否查询到了数据,输出
        SearchHit[] hits = scrollResp.getHits().getHits();
        if (hits != null && hits.length > 0) {
            System.out.println("----------下一页---------");
            for (SearchHit hit : hits) {
                System.out.println(hit.getSourceAsMap());
            }
        } else {
            //9. 判断没有查询到数据 -  退出循环
            System.out.println("----------下一页---------");
            break;
        }
    }


    //10. 创建 ClearScrollRequest
    ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
    //11. 指定 ScrollId
    clearScrollRequest.addScrollId(scrollId);
    //12. 删除 ScrollId
    ClearScrollResponse clearScrollResponse = client.clearScroll(clearScrollRequest, RequestOptions.DEFAULT);
    //13. 输出结果
    System.out.println("删除scroll: " + clearScrollResponse.isSucceeded());
}

与ElasticSearch 实现分词全文检索 - Scroll 深分页相似的内容:

ElasticSearch 实现分词全文检索 - Scroll 深分页

ES 对 from + size 有限制,两者之和不能超过1W Scroll查询方式,不适合做实时的查询,每次都是从数据文档中的ID去获取,效果高了,但文档中的ID(第二步)不是实时更新的,一般后台管理的方式用 Scroll 比较方便

ElasticSearch 实现分词全文检索 - 概述

ES 是一个使用Java语言并且基于Lucene编写的搜索引擎框架,他提供了分布式的全文搜索功能,提供了一个统一的基于Restful风格的WEB接口,官方客户端也对多种语言都提供了相应的API。

ElasticSearch 实现分词全文检索 - ES、Kibana、IK分词器安装

先把zip下载下来。放到任意一台服务器(直接github上下载多数会失败)elasticsearch-plugin install http://172.16.0.183:8899/Java/elasticsearch-analysis-ik-7.9.3.zip

ElasticSearch 实现分词全文检索 - Restful基本操作

GET 请求: ``` http://ip:port/index: 查询索引信息 http://ip;port/index/type/doc_id: 查询指定的文档信息 ``` POST 请求: ``` http://ip;port/index/type/_search: 查询文档,可以在请求体中添加json字符串来代表查询条件 http://ip;port/index/type/doc_id/

ElasticSearch 实现分词全文检索 - Java SpringBoot ES 索引操作

//1. 准备索引的 settings Settings.Builder settings = Settings.builder() //2. 准备索引的结构 Mappings XContentBuilder mappings = JsonXContent.contentBuilder() //3. 将 Settings 和 Mappings 封装到一个Request 对象中

ElasticSearch 实现分词全文检索 - Java SpringBoot ES 文档操作

//准备一个Request对象 IndexRequest request = new IndexRequest(indexName); request.id(person.getId().toString()); //手动指定ID request.source(personJson, XContentType.JSON); //通过 Client 对象执行

ElasticSearch 实现分词全文检索 - 测试数据准备

String json = JSON.toJSONStringWithDateFormat(sms, "yyyy-MM-dd HH:mm:ss"); FastJson 将日期格式化 BulkRequest bulkRequest = new BulkRequest(); Integer idx = 1; for (String json : jsonList) {

ElasticSearch 实现分词全文检索 - term、terms查询

term 查询 term的查询是代表完全匹配,搜索之前不会对你搜索的关键字进行分词,对你的关键字去文档分词库中的去匹配内容 terms和term的查询机制是一样,都不会将指定的查询关键字进行分词,直接去分词库中匹配,找到相应文档内容。 terms是在针对一个字段包含多个值的时候使用。 term: where province = 江苏 terms: where province = 江苏 or p

ElasticSearch 实现分词全文检索 - match、match_all、multimatch查询

match查询属于高层查询,他会根据你查询的字段类型不一样,采用不同的查询方式。 - 查询的是日期或者是数值的话,他会将你基于的字符串查询内容转换为日期或者数值对待。 - 如果查询的内容是一个不能被分词的内容 (keyword) ,match查询不会对你指定的查询关键字进行分词。 - 如果查询的内容时一个可以被分词的内容 (text),match会将你指定的查询内容根据一定的方式去分词,去分词库中

ElasticSearch 实现分词全文检索 - id、ids、prefix、fuzzy、wildcard、range、regexp 查询

fuzzy查询:模糊查询,我们输入字符的大概,ES就可以 wildcard 查询:通配查询,和MySQL中的 like 差不多,可以在查询时,在字符串中指定通配符 * 和占位符? range 查询:范围查询,只针对数值类型,对某一个Field进行大于或小于的范围指定查询 regexp 查询: 正则查询,通过你编写的正则表达式去匹配内容