zoukankan      html  css  js  c++  java
  • Elasticsearch:理解 mapping 中的 null_value

    转载自:https://elasticstack.blog.csdn.net/article/details/114266732

    null 不能被索引或搜索。 当字段设置为 null(或空数组或 所有值为 null 值的数组)时,将其视为该字段没有值。使用 null_value 参数可以用指定的值替换显式的空值,以便可以对其进行索引和搜索。 
    
    
    例子一
    
        PUT my-index-000001
        {
          "mappings": {
            "properties": {
              "status_code": {
                "type":       "keyword",
                "null_value": "NULL" 
              }
            }
          }
        }
    
    在上面,我们针对 status_code 字段定义其 null_value,也就是说当我们导入一个文档,当它的 status_code 指定为 null 时,那么在导入时,实际上它是被认为是 status_code 当做 "NULL" 被导入并进行分析。我们以下面的两个文档来进行说明:
    
        PUT my-index-000001/_doc/1
        {
          "status_code": null
        }
         
        PUT my-index-000001/_doc/2
        {
          "status_code": [] 
        }
    
    使用上面的两个命令写入两个文档到索引 my-index-000001 中。我们执行如下的搜索:
    
    GET my-index-000001/_search
    
    我们可以搜索到两个文档:
    
        {
          "took" : 1,
          "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-000001",
                "_type" : "_doc",
                "_id" : "1",
                "_score" : 1.0,
                "_source" : {
                  "status_code" : null
                }
              },
              {
                "_index" : "my-index-000001",
                "_type" : "_doc",
                "_id" : "2",
                "_score" : 1.0,
                "_source" : {
                  "status_code" : [ ]
                }
              }
            ]
          }
        }
    
    这显然是正确的,因为我们导入了两个文档。我们接着进行如下的搜索:
    
        GET my-index-000001/_search
        {
          "query": {
            "term": {
              "status_code": "NULL" 
            }
          }
        }
    
    上面的命令显示的结果为:
    
        {
          "took" : 1,
          "timed_out" : false,
          "_shards" : {
            "total" : 1,
            "successful" : 1,
            "skipped" : 0,
            "failed" : 0
          },
          "hits" : {
            "total" : {
              "value" : 1,
              "relation" : "eq"
            },
            "max_score" : 0.2876821,
            "hits" : [
              {
                "_index" : "my-index-000001",
                "_type" : "_doc",
                "_id" : "1",
                "_score" : 0.2876821,
                "_source" : {
                  "status_code" : null
                }
              }
            ]
          }
        }
    
    显然,第一个文档被搜索到,而第二个文档没有被搜索到。这是因为在第一个文档中,它清楚地指出 "status_code": null,所以在导入文档时,null_value 被认为是 status_code 而被导入并进行分析。第二个文档没有指定它是 null,所以没有被搜索出来。
    
    
    例子二
    
    假如我们有一下两个文档:
    
        PUT twitter/_doc/1
        {
          "age": null
        }
         
        PUT twitter/_doc/2
        {
          "age": 20
        }
    
    在上面,我们有两个文档。第一个文档的 age 值为 null,也就是说它不能被搜索到。假如我们做如下的聚合:
    
        GET twitter/_search
        {
          "size": 0,
          "aggs": {
            "avg_age": {
              "avg": {
                "field": "age"
              }
            }
          }
        }
    
    那么上面的聚合返回:
    
        {
          "took" : 2,
          "timed_out" : false,
          "_shards" : {
            "total" : 1,
            "successful" : 1,
            "skipped" : 0,
            "failed" : 0
          },
          "hits" : {
            "total" : {
              "value" : 2,
              "relation" : "eq"
            },
            "max_score" : null,
            "hits" : [ ]
          },
          "aggregations" : {
            "avg_age" : {
              "value" : 20.0
            }
          }
        }
    
    也就是说平均年龄是 20 岁,这是因为第一个文档被视为不见。我们怎么才能让第一个文档也参入聚合呢?我们可以使用 null_value 来为 null 值的字段设置一个值。我们修改 mapping 为:
    
        DELETE  twitter
         
        PUT twitter
        {
          "mappings": {
            "properties": {
              "age": {
                "type": "float",
                "null_value": 0
              }
            }
          }
        }
    
    我们再重新导入之前的两个文档:
    
        PUT twitter/_doc/1
        {
          "age": null
        }
         
        PUT twitter/_doc/2
        {
          "age": 20
        }
    
    由于我们已经定义当 age 为 null 时,null_value 将会起作用,它的值将为 0,那么这个文档将为可见。执行如下的聚合:
    
        GET twitter/_search
        {
          "size": 0,
          "aggs": {
            "avg_age": {
              "avg": {
                "field": "age"
              }
            }
          }
        }
    
    上面的结果为:
    
        {
          "took" : 703,
          "timed_out" : false,
          "_shards" : {
            "total" : 1,
            "successful" : 1,
            "skipped" : 0,
            "failed" : 0
          },
          "hits" : {
            "total" : {
              "value" : 2,
              "relation" : "eq"
            },
            "max_score" : null,
            "hits" : [ ]
          },
          "aggregations" : {
            "avg_age" : {
              "value" : 10.0
            }
          }
        }
    
    现在的平均值变为 10 了,也就是 (20 + 0)/2 = 10。
    
    这里必须注意的是,我们必须显示地指定 age 为 null,否则 null_vale 将不会起任何的作用。比如:
    
        DELETE twitter
         
        PUT twitter
        {
          "mappings": {
            "properties": {
              "age": {
                "type": "float",
                "null_value": 0
              }
            }
          }
        }
         
        PUT twitter/_doc/1
        {
          "content": "This is cool"
        }
         
        PUT twitter/_doc/2
        {
          "age": 20,
          "content": "This is cool too!"
        }
    
    在上面,第一个文档里没有定义 age,那么 null_value 将不会起作用。如果我们做如下的聚合:
    
        GET twitter/_search
        {
          "size": 0,
          "aggs": {
            "avg_age": {
              "avg": {
                "field": "age"
              }
            }
          }
        }
    
    其显示结果为:
    
        {
          "took" : 1,
          "timed_out" : false,
          "_shards" : {
            "total" : 1,
            "successful" : 1,
            "skipped" : 0,
            "failed" : 0
          },
          "hits" : {
            "total" : {
              "value" : 2,
              "relation" : "eq"
            },
            "max_score" : null,
            "hits" : [ ]
          },
          "aggregations" : {
            "avg_age" : {
              "value" : 20.0
            }
          }
        }
    
    也就是说第一个文档没有被搜索到。
    
    
  • 相关阅读:
    2018年第九届蓝桥杯国赛总结(JavaB组)
    yzm10的小简介
    论文学习笔记
    Tied Block Convolution:一种共享filter的卷积形态
    AI艺术鉴赏挑战赛
    论文学习笔记
    (转)论文学习笔记
    论文学习笔记
    2020 计蒜之道 预赛 第三场 石子游戏(简单)(暴力DP)
    第六周:生成式对抗网络
  • 原文地址:https://www.cnblogs.com/sanduzxcvbnm/p/14570768.html
Copyright © 2011-2022 走看看