ElasticSearch系列 - SpringBoot整合ES:查询字段不为空的文档 exists

Posted 我一直在流浪

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ElasticSearch系列 - SpringBoot整合ES:查询字段不为空的文档 exists相关的知识,希望对你有一定的参考价值。

文章目录

1. ElasticSearch exists 查询是什么

在某些场景下,我们希望找到某个字段不为空的文档,则可以用exists搜索。字段不为空的条件有:

值存在且不是 null;

值不是空数组;

值是数组,但不是 [null]

例如,查询在字段中至少有一个非空值的文档:

GET /_search

    "query": 
        "exists" :  "field" : "user" 
    

这些文档都将匹配上面的查询:

 "user": "jane" 
 "user": ""  "user": "-"  "user": ["jane"] 
 "user": ["jane", null ] 

① 空字符串是 non-null (非空值)。

② 即使通过 standard analyzer 标准分析器也不会发出警告,原始字段也是非空的。

③ 至少需要一个 non-null 非空值。

这些文档将不会被上面的查询匹配到:

 "user": null 
 "user": []  ①
 "user": [null]  ②
 "foo":  "bar"  ③

① 这个字段没有任何值。

② 至少需要一个 non-null 非空值。

③ user 字段完全丢失。

2. ElasticSearch exists 查询字段值存在且不是 null 的文档

在某些场景下,我们希望找到某个字段不为空的文档,则可以用exists搜索。字段不为空的条件有:

值存在且不是 null;

值不是空数组;

值是数组,但不是 [null]

① 索引文档

PUT /my_index

  "mappings": 
    "properties": 
      "tag":
        "type": "keyword"
      
    
  


PUT /my_index/_doc/1

  "tag":null


PUT /my_index/_doc/2

  "tag":""


PUT /my_index/_doc/3

  "tag":"C"

② 查询 tag 字段值存在且不是 null 的文档

GET /my_index/_search

  "query": 
    "exists": "field": "tag"
  


  "took" : 10,
  "timed_out" : false,
  "_shards" : 
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  ,
  "hits" : 
    "total" : 
      "value" : 2,
      "relation" : "eq"
    ,
    "max_score" : 1.0,
    "hits" : [
      
        "_index" : "my_index",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 1.0,
        "_source" : 
          "tag" : ""
        
      ,
      
        "_index" : "my_index",
        "_type" : "_doc",
        "_id" : "3",
        "_score" : 1.0,
        "_source" : 
          "tag" : "C"
        
      
    ]
  

3. ElasticSearch exists 查询字段值不是空数组的文档

① 索引文档,构造数据:

PUT /my_index

  "mappings": 
    "properties": 
      "tag":
        "type": "keyword"
      
    
  


PUT /my_index/_doc/2

  "tag":[]


PUT /my_index/_doc/4

  "tag":["A"]

② 查询 tag 字段值不是空数组的文档

GET /my_index/_search

  "query": 
    "exists": "field": "tag"
  


  "took" : 3,
  "timed_out" : false,
  "_shards" : 
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  ,
  "hits" : 
    "total" : 
      "value" : 1,
      "relation" : "eq"
    ,
    "max_score" : 1.0,
    "hits" : [
      
        "_index" : "my_index",
        "_type" : "_doc",
        "_id" : "4",
        "_score" : 1.0,
        "_source" : 
          "tag" : [
            "A"
          ]
        
      
    ]
  

4. ElasticSearch exists 查询字段值是数组但不是 [null] 的文档

① 索引文档,构造数据:

PUT /my_index

  "mappings": 
    "properties": 
      "tag":
        "type": "keyword"
      
    
  


PUT /my_index/_doc/3

  "tag":[null]


PUT /my_index/_doc/4

  "tag":["A"]

② 查询 tag 字段值是数组但不是 [null] 的文档


  "took" : 5,
  "timed_out" : false,
  "_shards" : 
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  ,
  "hits" : 
    "total" : 
      "value" : 1,
      "relation" : "eq"
    ,
    "max_score" : 1.0,
    "hits" : [
      
        "_index" : "my_index",
        "_type" : "_doc",
        "_id" : "4",
        "_score" : 1.0,
        "_source" : 
          "tag" : [
            "A"
          ]
        
      
    ]
  

5. ElasticSearch exists 查询文档中是否存在指定的字段

exist查询来检查文档中是否存在指定的字段或属性

① 索引文档,构造数据:

PUT /my_index

  "mappings": 
    "properties": 
      "tag":
        "type": "keyword"
      
    
  


PUT /my_index/_doc/4

  "tag":["A"]

② 查询存在 tag 字段的文档:

用exists查询来检查文档中是否存在“tag”字段。如果存在,则该文档将被返回。如果不存在,则该文档将被过滤掉。

GET /my_index/_search

  "query": 
    "exists": "field": "tag"
  


  "took" : 1,
  "timed_out" : false,
  "_shards" : 
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  ,
  "hits" : 
    "total" : 
      "value" : 1,
      "relation" : "eq"
    ,
    "max_score" : 1.0,
    "hits" : [
      
        "_index" : "my_index",
        "_type" : "_doc",
        "_id" : "4",
        "_score" : 1.0,
        "_source" : 
          "tag" : [
            "A"
          ]
        
      
    ]
  

6. SpringBoot 整合ES实现exist查询

@Slf4j
@Service
public class ElasticSearchImpl 

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    public void searchUser() throws IOException 
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        // exist查询
        ExistsQueryBuilder existsQueryBuilder = new ExistsQueryBuilder("tag");
        searchSourceBuilder.query(existsQueryBuilder);

        SearchRequest searchRequest = new SearchRequest(new String[]"my_index",searchSourceBuilder);
        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        System.out.println(searchResponse);
    

ExistsQueryBuilder 源码:

public class ExistsQueryBuilder extends AbstractQueryBuilder<ExistsQueryBuilder> 
    public static final String NAME = "exists";

    public static final ParseField FIELD_FIELD = new ParseField("field");

    private final String fieldName;

    public ExistsQueryBuilder(String fieldName) 
        if (Strings.isEmpty(fieldName)) 
            throw new IllegalArgumentException("field name is null or empty");
        
        this.fieldName = fieldName;
    

Elasticsearch系列---初识Elasticsearch

Elasticsearch是什么?

Elasticsearch简称ES,是一个基于Lucene构建的开源、分布式、Restful接口的全文搜索引擎,还是一个分布式文档数据库。天生就是分布式、高可用、可扩展的,可以在很短的时间内存储、搜索和分析大量的数据。

什么是全文搜索?

全文搜索也叫全文检索,是指扫描文章中的每一个词,对每一个词进建立一个索引,指明该词在文章中出现的次数和位置,当前端用户输入的关键词发起查询请求后,搜索引擎就会根据事先建立的索引进行查找,并将查询的结果响应给用户。
这里有两个关键字:分词和索引,Elasticsearch内部会完成这两件事情,对保存的文本内容按规则进行分词,并对这些分词后的词条建立索引,供用户查询。

什么是倒排索引?

全文搜索过程根据关键词创建的索引叫倒排索引,顾名思义,建立正向关系“文本内容-关键词”叫正排索引,后续会介绍,倒排索引就是把原有关系倒过来,建立成“关键词-文本内容”的关系,这样的关系非常利于搜索。
举个例子:

  • 文本1:I have a friend who loves smile
  • 文本2:I have a dream today

先进行英文分词,再建立倒排索引,得到一份简易的“关键词-文本”的映射关系如下:

关键词 文本编号
I 1,2
have 1,2
a 1,2
friend 1
who 1
loves 1
smile 1
dream 2
today 2

有了这个映射表,搜索"have"关键词时,立即就能返回id为1,2的两条记录,搜索today时,返回id为2的记录,这样的搜索性能非常高。当然Elasticsearch维护的倒排索引包含更多的信息,此处只是作简易的原理介绍。

Elasticsearch什么场景适用?

常见场景
  1. 搜索类场景
    常见的搜索场景比如说电商网站、招聘网站、新闻资讯类网站、各种app内的搜索。

  2. 日志分析类场景
    经典的ELK组合(Elasticsearch/Logstash/Kibana),可以完成日志收集,日志存储,日志分析查询界面基本功能,目前该方案的实现很普及,大部分企业日志分析系统都是使用该方案。

  3. 数据预警平台及数据分析场景
    例如电商价格预警,在支持的电商平台设置价格预警,当优惠的价格低于某个值时,触发通知消息,通知用户购买。
    数据分析常见的比如分析电商平台销售量top 10的品牌,分析博客系统、头条网站top 10关注度、评论数、访问量的内容等等。

  4. 商业BI系统
    比大型零售超市,需要分析上一季度用户消费金额,年龄段,每天各时间段到店人数分布等信息,输出相应的报表数据,并预测下一季度的热卖商品,根据年龄段定向推荐适宜产品。Elasticsearch执行数据分析和挖掘,Kibana做数据可视化。

常见案例
  • 维基百科、百度百科:有全文检索、高亮、搜索推荐功能
  • stack overflow:有全文检索,可以根据报错关键信息,去搜索解决方法。
  • github:从上千亿行代码中搜索你想要的关键代码。
  • 日志分析系统:各企业内部搭建的ELK平台。
  • 等等

Elasticsearch的架构图

技术图片

架构各组件简单释义:

  • gateway 底层存储系统,一般为文件系统,支持多种类型。
  • distributed lucence directory 基于lucence的分布式框架,封装了建立倒排索引、数据存储、translog、segment等实现。
  • 模块层 ES的主要模块,包含索引模块、搜索模块、映射模块。
  • Discovery 集群node发现模块,用于集群node之间的通信,选举coordinate node操作,支持多种发现机制,如zen,ec2等。
  • script 脚本解析模块,用来支持在查询语句中编写的脚本,如painless,groovy,python等。
  • plugins 第三方插件,各种高级功能可由插件提供,支持定制。
  • transport/jmx 通信模块,数据传输,底层使用netty框架
  • restful/node 对外提供的访问Elasticsearch集群的接口
  • x-pack elasticsearch的一个扩展包,集成安全、警告、监视、图形和报告功能,无缝接入,可插拔设计。

Elasticsearch安装使用

官网地址

https://www.elastic.co/cn/
上面有各版本的下载地址,官方文档和使用示例,请自行下载安装包。

源码地址

https://github.com/elastic/elasticsearch
上面有各版本的源码地址,可以切换到指定版本进行研究,目前选用版本为6.3.1

安装步骤
  1. 环境要求
    JDK 1.8及以上
  2. 官网下载安装包,在指定目录下直接解压
  3. 执行bin/elasticsearch(Linux,注意不能使用root账户)
    binelasticsearch.bat(Windows)
  4. curl http://localhost:9200/或浏览器打开http://localhost:9200/地址,看到下面的响应表示启动成功
{
  "name" : "node-1",
  "cluster_name" : "hy-application",
  "cluster_uuid" : "lJ4DRWOvQauAy-VEYiZc2g",
  "version" : {
    "number" : "6.3.1",
    "build_flavor" : "default",
    "build_type" : "tar",
    "build_hash" : "eb782d0",
    "build_date" : "2018-06-29T21:59:26.107521Z",
    "build_snapshot" : false,
    "lucene_version" : "7.3.1",
    "minimum_wire_compatibility_version" : "5.6.0",
    "minimum_index_compatibility_version" : "5.0.0"
  },
  "tagline" : "You Know, for Search"
}
  1. kibana下载解压启动
    执行bin/kibana(Linux,注意不能使用root账户)或binkibana.bat(Windows),如果kibana和elasticsearch部署在同一台机器上,使用默认的配置文件即可。
  2. 验证kibana,浏览器上输入http://192.168.17.137:5601/,出现如下界面表示启动成功:
    图二

小结

本篇简单介绍了Elasticsearch的基本概念,适用场景和主要的功能框架,以及最简单的用于学习验证的安装启动步骤,作为Elasticsearch系统的开篇学习,Elasticsearch有个特点就是开箱即用,如果是用作学习,或是中小型应用,数据量比较少、操作不是很复杂的话,直接启动就可以用了。后续的Elasticsearch学习,如无特别说明,均以6.3.1版本为例。

专注Java高并发、分布式架构,更多技术干货分享与心得,请关注公众号:Java架构社区
技术图片

以上是关于ElasticSearch系列 - SpringBoot整合ES:查询字段不为空的文档 exists的主要内容,如果未能解决你的问题,请参考以下文章

SpringCloud系列研究---Eureka服务注册

ElasticSearch系列之什么是ElasticSearch?

Spring Boot 2系列教程

剖析Elasticsearch集群系列第一篇 Elasticsearch的存储模型和读写操作

ElasticSearch 系列随笔

ElasticSearch系列之什么是ElasticSearch?