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

elasticsearch,实现,分词,全文检索,id,ids,prefix,fuzzy,wildcard,range,regexp,查询 · 浏览次数 : 246

小编点评

**ElasticSearch 实现分词全文检索** **概述** ElasticSearch 提供分词功能,允许您将搜索文本中的多个单词或分词词搜索匹配的文档。这使您可以构建更精细的搜索表达式,以提高搜索效率。 **安装和配置** 1. 下载并安装 Elasticsearch 版本 7.x 或更高版本。 2. 配置您的系统环境变量 `ES_HEAP_SIZE` 以指定 Elasticsearch 中可使用的内存量。 **RESTful 基本操作** 1. 使用 `GET` 方法在 `_search` 路径下搜索文档。 2. 搜索条件可以包括文本搜索、正则表达式搜索和范围搜索。 3. 使用 `fields` 参数指定要搜索的字段。 4. 使用 `score` 参数指定搜索结果的排序方式。 **分词搜索示例** ```json { "query": { "match": { "content": { "query": "hello world", "operator": "and" } } } } ``` 这查询将搜索 `content` 字段中包含单词 "hello" 和 "world" 的文档。 **高级搜索选项** * `match_phrase`: 使用正则表达式匹配多个单词或分词词。 * `fuzzy`: 使用分词搜索匹配字符串中的多个词。 * `prefix_match`: 在字符串开头匹配词。 * `range`: 在字符串中匹配特定范围的数字值。 * `regexp`: 使用正则表达式匹配字符串中的内容。 **性能优化** * 使用 `_search` 路径而不是 `_query` 路径进行搜索,以提高性能。 * 使用 `field_weights` 和 `min_score` 参数优化搜索结果的排序。 * 使用 `highlight` 参数显示搜索结果中的关键词。 **示例代码** ```python import elasticsearch # 连接到 Elasticsearch 实例 client = elasticsearch.elasticsearch.Elasticsearch(hosts="localhost:9200") # 搜索文本 response = client.search(index="my_index", body={"query": {"match": {"content": "hello world"}}}) # 打印结果 print(response.ogenes) ``` **总结** ElasticSearch 提供分词搜索功能,允许您轻松构建精细的搜索表达式以提高搜索效率。通过使用高级搜索选项和性能优化,您可以进一步提高搜索性能。

正文

目录

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 实现分词全文检索 - 测试数据准备

id 查询

# id 查询
GET /sms-logs-index/_doc/1

Java

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

    //1. 创建GetRequest对象
    GetRequest request = new GetRequest(indexName,"1");

    //2. 执行查询
    GetResponse resp = client.get(request, RequestOptions.DEFAULT);

    //4. 获取到  中的数据,并展示
    System.out.println(resp.getSourceAsMap());
}

ids 查询

根据多个ID查询,类似MySQL中的 where id in (1,2,3)

# ids 查询
GET /sms-logs-index/_search/
{
  "query": {
    "ids": {
      "values": ["1","2","3"]
    }
  }
} 

Java

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

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

    //2. 指定查询条件
    SearchSourceBuilder builder = new SearchSourceBuilder();
    builder.query(QueryBuilders.idsQuery().addIds("1","2","3"));
    request.source(builder);

    //3. 执行查询
    SearchResponse resp = client.search(request, RequestOptions.DEFAULT);

    //4. 获取到 _source 中的数据,并展示
    for (SearchHit hit : resp.getHits().getHits()) {
        Map<String, Object> result = hit.getSourceAsMap();
        System.out.println(result);
    }
}

prefix查询

前缀查询,可以通过一个关键字去指定一个Field的前缀,从而查询到指定的文档

# prefix 查询
GET /sms-logs-index/_search/
{
  "query": {
    "prefix": {
      "longCode": {
        "value": "李"
      }
    }
  }
}

Java

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

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

    //2. 指定查询条件
    SearchSourceBuilder builder = new SearchSourceBuilder();
    builder.query(QueryBuilders.prefixQuery("longCode","李"));
    request.source(builder);

    //3. 执行查询
    SearchResponse resp = client.search(request, RequestOptions.DEFAULT);

    //4. 获取到 _source 中的数据,并展示
    for (SearchHit hit : resp.getHits().getHits()) {
        Map<String, Object> result = hit.getSourceAsMap();
        System.out.println(result);
    }
}

fuzzy查询

模糊查询,我们输入字符的大概,ES就可以

# fuzzy 查询
GET /sms-logs-index/_search/
{
  "query": {
    "fuzzy": {
      "smsContent": {
        "value": "天天凯心", # 可以有错别字
        "prefix_length": 2  # 前N个字符,不允许出现错误,完本匹配
      }
    }
  }
}

Java

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

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

    //2. 指定查询条件
    SearchSourceBuilder builder = new SearchSourceBuilder();
    builder.query(QueryBuilders.fuzzyQuery("smsContent","天天凯心").prefixLength(2));
    request.source(builder);

    //3. 执行查询
    SearchResponse resp = client.search(request, RequestOptions.DEFAULT);

    //4. 获取到 _source 中的数据,并展示
    for (SearchHit hit : resp.getHits().getHits()) {
        Map<String, Object> result = hit.getSourceAsMap();
        System.out.println(result);
    }
}

wildcard 查询

通配查询,和MySQL中的 like 差不多,可以在查询时,在字符串中指定通配符 * 和占位符?

# wildcard 查询
GET /sms-logs-index/_search/
{
  "query": {
    "wildcard": {
      "smsContent": {
        "value": "天*"
      }
    }
  }
}

Java

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

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

    //2. 指定查询条件
    SearchSourceBuilder builder = new SearchSourceBuilder();
    builder.query(QueryBuilders.wildcardQuery("smsContent","天*"));
    request.source(builder);

    //3. 执行查询
    SearchResponse resp = client.search(request, RequestOptions.DEFAULT);

    //4. 获取到 _source 中的数据,并展示
    for (SearchHit hit : resp.getHits().getHits()) {
        Map<String, Object> result = hit.getSourceAsMap();
        System.out.println(result);
    }
}

range 查询

范围查询,只针对数值类型,对某一个Field进行大于或小于的范围指定查询

# wildcard 查询
GET /sms-logs-index/_search/
{
  "query": {
    "range": {
      "fee": {
        "gte": 10,
        "lte": 20
      }
    }
  }
}

Java

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

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

    //2. 指定查询条件
    SearchSourceBuilder builder = new SearchSourceBuilder();
    builder.query(QueryBuilders.rangeQuery("fee").gte(10).lte(20));
    request.source(builder);

    //3. 执行查询
    SearchResponse resp = client.search(request, RequestOptions.DEFAULT);

    //4. 获取到 _source 中的数据,并展示
    for (SearchHit hit : resp.getHits().getHits()) {
        Map<String, Object> result = hit.getSourceAsMap();
        System.out.println(result);
    }
}

regexp 查询

正则查询,通过你编写的正则表达式去匹配内容

PS:prefix,fuzzy,wildcard 和 regexp 查询效率相对比较低。要求效率比较高时,避免去使用]

# regexp 查询
POST /sms-logs-index/_search/
{
  "query": {
    "regexp": {
      "mobile": "1382[0-9]{7}" # 查询 1382开头的手机号
      }
    }
  }
}

Java

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

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

    //2. 指定查询条件
    SearchSourceBuilder builder = new SearchSourceBuilder();
    builder.query(QueryBuilders.regexpQuery("mobile","1382[0-9]{7}"));
    request.source(builder);

    //3. 执行查询
    SearchResponse resp = client.search(request, RequestOptions.DEFAULT);

    //4. 获取到 _source 中的数据,并展示
    for (SearchHit hit : resp.getHits().getHits()) {
        Map<String, Object> result = hit.getSourceAsMap();
        System.out.println(result);
    }
}

与ElasticSearch 实现分词全文检索 - id、ids、prefix、fuzzy、wildcard、range、regexp 查询相似的内容:

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

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

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 文档操作

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

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

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

ElasticSearch 实现分词全文检索 - delete-by-query

delete-by-query 根据 term、match 等查询方式去删除大量的文档 > 如果需要删除的内容,是index下的大部分数据,不建议使用,因为去匹配文档时还是一个一个的拿到文档ID,去删除 推荐创建一个全新的index,将保留的文档内容,添加到全新的索引中

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 实现分词全文检索 - Java SpringBoot ES 索引操作

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

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