es--基础--9.3--SpringBoot注解--Field--FieldType

es–基础–9.3–SpringBoot注解–Field–FieldType


内容

public enum FieldType {
	Auto, //
	Text, //
	Keyword, //
	Long, //
	Integer, //
	Short, //
	Byte, //
	Double, //
	Float, //
	Half_Float, //
	Scaled_Float, //
	Date, //
	Date_Nanos, //
	Boolean, //
	Binary, //
	Integer_Range, //
	Float_Range, //
	Long_Range, //
	Double_Range, //
	Date_Range, //
	Ip_Range, //
	Object, //
	Nested, //
	Ip, //
	TokenCount, //
	Percolator, //
	Flattened, //
	Search_As_You_Type, //
	/** @since 4.1 */
	Rank_Feature, //
	/** @since 4.1 */
	Rank_Features //
}

1、字符串 类型

1.1、Text

  1. 默认会进行分词
  2. 会被分词器解析,生成倒排索引
  3. 支持模糊、精确查询
  4. 不用于排序,很少用于聚合(significant text aggregation除外)
  5. 常用于全文检索,如果需要为结构化内容,比如 id、email、hostnames、状态码、标签等进行索引,则推荐使用 keyword 类型以进行完全匹配,比如我们需要查询"已发货"的订单,标记为"已发布"的文章等。
PUT my_index
{
  "mappings": {
    "properties": {
      "full_name": {
        "type":  "text"
      }
    }
  }
}

1.2、Keyword

  1. 不进行分词
  2. 直接索引
    1. 直接索引:索引直接指向物理块(地址直接对应物理盘块存索引的内容)
    2. 间接地址索引:索引节点指向的物理块用来存放地址项
  3. 支持模糊、精确查询
  4. 支持聚合
  5. ES会对"数值(numeric)"类型的字段(比如,integer,long)进行优化以支持范围(range)查询。但是,不是所有的数值类型的数据都需要使用"数值"类型,比如产品id,会员id,ISDN(出版社编号),这些很少会被进行范围查询,通常都是精确匹配(term query)。
    1. keyword类型的查询通常比numeric的要快,如果不需要范围查询,则建议使用keyword类型。
    2. 如果不确定使用哪一种,可以通过multi-field同时设置keyword和numeric类型。
PUT my_index
{
  "mappings": {
    "properties": {
      "tags": {
        "type":  "keyword"
      }
    }
  }
}

2、数值类型(numeric)

在这里插入图片描述

  1. 默认建立索引

2.1、案例

PUT my_index
{
  "mappings": {
    "properties": {
      "number_of_bytes": {
        "type": "integer"
      },
      "time_in_seconds": {
        "type": "float"
      },
      "price": {
        "type": "scaled_float",
        "scaling_factor": 100
      }
    }
  }
}

上面我们定义了3个字段:

  1. number_of_bytes: 整型,integer
  2. time_in_seconds: 浮点型,float
  3. price:
    1. 带有缩放因子scaling_factor的浮点数,比如价格是99.99,缩放因子为100,那么存储的值就是long类型的9999。
    2. 这种方式我们在数据库中也经常使用,比如我们在mysql中存储价格,只需要精确到分的话,我们可以使用decimal(12,2)或者int类型,使用int类型可以节省空间而且不存在精度转换问题,但是我们必须在业务逻辑中使用缩放因子进行转换,而ES的scaled_float直接帮我们处理了。

2.2、浮点类型

对于上面展示的3种浮点类型(float,half_float,scaled_float)来说, -0.00和+0.00是不同的值

  1. 对于term查询:-0.00时不会匹配+0.00,反之亦然。
  2. 对于范围查询(range query):
    1. 如果上边界是-0.00,则无法匹配+0.00
    2. 如果下边界是+0.00,则不会匹配-0.00

2.3、注意事项–尽量选择范围小的类型

  1. 在满足业务需求的情况下,尽量选择范围小的类型,这与mysql等关系型数据库的设计要求是一致的。
  2. 字段占用的空间越小,搜索和索引的效率越高

2.4、注意事项–如果是浮点数,优先考虑使用scaled_float类型

  1. 对于scaled_float类型,在索引时会乘以scaling_factor并四舍五入到最接近的一个long类型的值。
  2. 如果我们存储商品价格只需要精确到分,两位小数点,把缩放因子设置为100,那么浮点价格99.99存储的是9999。
  3. 如果我们要存储的值是2.34,而因子是10,那么会存储为23,在查询/聚合/排序时会表现为这个值是2.3。 如果设置更大的因子(比如100),可以提高精度,但是会增加空间需求。
  4. scaled_float在查询时的的数据处理应该与mysql类似,比如:
    使用这个写法
    SELECT * FROM products WHERE price > 99.99 * 100
    不使用这个写法,改写法不符合mysql优化原则:不要对栏位进行函数运算以及类型转换
    SELECT * FROM products WHERE price / 100 > 99.99
    

3、Object 类型

  1. 嵌套类型,不支持数组。

3.1、JSON文档天生具有层级关系

文档可能包含内部对象,而这个对象可能本身又包含对象,就是可以包含嵌套的对象。

PUT my_index2/_doc/1
{
  "region":"US",
  "manager":{
    "age":30,
    "name":{
      "first":"John",
      "last":"Smith"
    }
  }
}

上面的文档中,整体是一个JSON,JSON中包含一个manager,manager又包含一个name。最终,文档会被索引成一平的key-value对。

3.2、文档会被索引成一平的key-value对

{
  "region":             "US",
  "manager.age":        30,
  "manager.name.first": "John",
  "manager.name.last":  "Smith"
}

3.3、上面那个文档的mapping可以显式声明如下

PUT my_index2
{
  "mappings": {
    "properties":{
      "region":{
        "type": "keyword"
      },
      "manager":{
        "properties": {
          "age":{"type":"integer"},
          "name":{
            "properties":{
              "first":{"type":"text"},
              "last":{"type":"text"}
            }
          }
        }
      }
    }
  }
}

这个索引有2个一级字段: region,manager;
而manager是一个对象类型,又包含字段age和name,可以写为 manager.age, manager.name;
而字段 manager.name 又是一个包含first和last的对象。

3.4、内部对象的type就是object

  1. 不需要我们显式的去声明,但是我们写上去也没错。

在这里插入图片描述

4、Date 类型

  1. 日期类型
  2. 默认不建立索引

4.1、表现形式

JSON没有日期(date)类型,在ES中date类型表现形式

  1. 字符串格式的日期:比如: “2015-01-01”,“2015/01/01 12:10:30”
  2. long类型:自 1970-1-1 以来的毫秒数
  3. integer类型:自 1970-1-1 以来的秒数(时间戳,timestamp)

4.2、存储

在ES内部,日期被转换为UTC格式(如果指定了时区),并存储为long类型,自1970-1-1 以来的毫秒数。

4.3、查询时

  1. date类型会在内部转换为long类型的范围查询
  2. 聚合和存储字段的结果根据与字段关联的日期格式转换回字符串。
    1. date总是被显示为字符串格式,即使他们在JSON文档中是long类型

4.4、自定义date的格式

  1. 如果没有指定format,则默认格式为: strict_date_optional_time || epoch_millis,其中的"||"是 "multiple formats"的分隔符.
  2. strict_date_optional_time 格式:指ISO标准格式,例如: yyyy-MM-dd’T’HH:mm:ss.SSSZ 或者 yyyy-MM-dd

4.5、操作

DELETE my_index
 
# 使用默认格式
PUT my_index
{
  "mappings": {
    "properties": {
      "date":{
        "type": "date"
      }
    }
  }
}
# 纯日期
PUT my_index/_doc/1
{ "date": "2015-01-01" }
# 包含时间
PUT my_index/_doc/2
{ "date": "2015-01-01T12:10:30Z" }
# 使用long格式的毫秒值
PUT my_index/_doc/3
{ "date": 1420070400001 }

4.5.1、查看

GET my_index/_search?filter_path=hits.hits

在这里插入图片描述

4.5.2、排序

排序结果: sort栏位是一个long类型的毫秒值

GET my_index/_search?filter_path=hits.hits
{
  "sort": { "date": "asc"} 
}

在这里插入图片描述

4.6、Multiple date formats

  1. 使用 “||” 作为分隔符来让日期支持多种格式
  2. 会轮流尝试每一种格式,直到与之相匹配,第1种格式会被用来把毫秒值转换回字符串。
PUT my_index
{
  "mappings": {
    "properties": {
      "date": {
        "type":   "date",
        "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
      }
    }
  }
}


5、Array 类型

  1. ELasticsearch没有独立的数组类型,默认情况下任何字段都可以包含一个或者多个值,但是数组中的值必须是同一种类型。
  2. 动态添加数组类型的字段时,数组中的第一个值决定了它的字段类型,后面的值必须具有相同的数据类型,或者至少可以将后续值强制转换为相同的数据类型。
  3. 混合类型的值是不被数组支持的,比如 [ 10, “some string” ] 是不被支持的。
  4. 数组可以包含null值,它会被配置的 null_value 替代 或者 直接被忽略。
  5. 空数组 [] 会被当做missing field对待。

5.1、数组中的值必须是同一种类型

  1. 字符串数组: [ “one”, “two” ]
  2. 整型数组:[ 1, 2 ]
  3. 嵌套数组:[ 1, [ 2, 3 ]],它等价于 [ 1, 2, 3 ]
  4. 对象数组:[ { “name”: “Mary”, “age”: 12 }, { “name”: “John”, “age”: 10 }]

5.2、要在文档中使用数组,无需预先配置,它们受到开箱即用的支持

PUT my_index4/_doc/1
{
  "message": "has arrays",
  "tags":["es", "mysql"],
  "lists":[
    {
      "name":"java", 
      "description":"java book"
    }
    ,{
      "name":"python",
      "description":"python book"
    }
  ]
}
PUT my_index4/_doc/2
{
  "message":"no arrays",
  "tags":"es",
  "lists":{
    "name":"java",
    "description":"use java"
  }
}
GET my_index4/_search
{
  "query":{
    "match": {
      "tags": "es"
    }
  }
}

  1. id=1的文档,动态的添加了2个字段
    1. 字符串类型数组:tags
    2. 对象类型:lists
  2. id=2的文档,没有数组类型的字段,但是可以像id=1的文档一样,tags存储到到对应的字段里面去。
  3. 当我们搜索"tags"等于"es"的时候,两个文档都是匹配的。

5.3、查看_mapping

GET my_index4/_mapping
{
  "my_index4" : {
    "mappings" : {
      "properties" : {
        "lists" : {
          "properties" : {
            "description" : {
              "type" : "text",
              "fields" : {
                "keyword" : {
                  "type" : "keyword",
                  "ignore_above" : 256
                }
              }
            },
            "name" : {
              "type" : "text",
              "fields" : {
                "keyword" : {
                  "type" : "keyword",
                  "ignore_above" : 256
                }
              }
            }
          }
        },
        "message" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "tags" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        }
      }
    }
  }
}

我们可以看到,lists是object类型,message和tags都是text类型!

6、Binary 类型

  1. 二进制类型
  2. 值以Base64字符串的形式存储
  3. store属性:
    1. false(默认):_source不会存储该类型的值,也不可搜索
    2. true:_source会存储该类型的值

6.1、创建索引和数据

DELETE /my_index
# 新增一个索引
PUT /my_index
{
  "mappings": {
    "properties": {
      "name": {
        "type": "text"
      },
      "name_blob": {
        "type": "binary",
        "doc_values": false,
        "store": false
      }
    }
  }
}
# 添加一个文档
PUT /my_index/_doc/1
{
  "name": "aben",
  "name_blob": "YWJlbg=="
}

6.2、直接搜索name_blob列,会报错,因为不可搜索

GET /my_index/_search
{
  "query": {
    "match": {
      "name": "aben"
    }
  }
}

在这里插入图片描述

7、Ip 类型

只能存储ipv4或ipv6地址

7.1、创建数据




DELETE /my_index
# 新增一个索引
PUT my_index
{
  "mappings": {
    "properties": {
      "ip_addr": {
        "type": "ip"
      }
    }
  }
}
POST _bulk
{"index":{"_index":"my_index", "_id":1}}
{"ip_addr":"192.168.1.1"}
{"index":{"_index":"my_index", "_id":2}}
{"ip_addr":"192.168.2.1"}
{"index":{"_index":"my_index", "_id":3}}
{"ip_addr":"192.168.0.1"}
{"index":{"_index":"my_index", "_id":4}}
{"ip_addr":"192.168.1.10"}
{"index":{"_index":"my_index", "_id":5}}
{"ip_addr":"192.168.3.1"}
{"index":{"_index":"my_index", "_id":6}}
{"ip_addr":"192.169.1.169"}

7.2、查看IP4


# 查询ip是192.168段的文档
GET my_index/_search
{
  "query": {
    "term": {
      "ip_addr": "192.168.0.0/16"
    }
  }
}
# 查询ip是192.168.0段的文档
GET my_index/_search
{
  "query": {
    "term": {
      "ip_addr": "192.168.0.0/24"
    }
  }
}

7.3、查看IP6

GET my_index/_search
{
  "query": {
    "term": {
      "ip_addr": "2001:db8::/48"
    }
  }
}

8、range类型

在这里插入图片描述

8.1、创建数据


DELETE /range_index

# 定义一个索引, 有2个字段: expected_attendees是整数范围, time_frame是日期范围
PUT /range_index
{
  "mappings": {
    "properties": {
      "expected_attendees": {
        "type": "integer_range"
      },
      "time_frame": {
        "type": "date_range",
        "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
      }
    }
  }
}


# 插入数据: expected_attendees取值范围为10~20, 日期time_frame的范围是2015-10-31 12:00:00 ~ 2015-11-01
PUT /range_index/_doc/1?refresh
{
  "expected_attendees" : {
    "gte" : 10,
    "lte" : 20
  },
  "time_frame" : {
    "gte" : "2015-10-31 12:00:00",
    "lte" : "2015-11-01"
  }
}

8.2、查询

term类型的查询 就是判断某一个值是否有对应的范围的记录存在


# 整数范围查询
## 查询 expected_attendees=12 是否有对应的范围值
GET range_index/_search
{
  "query" : {
    "term" : {
      "expected_attendees" : {
        "value": 12
      }
    }
  }
}
# 日期范围查询
## 查询某一个日期是否有对应的范围值
GET range_index/_search
{
  "query" : {
    "term" : {
      "time_frame" : {
        "value" : "2015-10-31 13:00:00"
      }
    }
  }
}
## 范围查询支持 within, contains, intersects(默认)
GET range_index/_search
{
  "query" : {
    "range" : {
      "time_frame" : { 
        "gte" : "2015-10-30 11:00:00",
        "lte" : "2015-11-01 08:00:00",
        "relation" : "within"
      }
    }
  }
}

8.3、查询ip范围的案例

# IP范围类型
PUT /range_index2
{
  "mappings": {
    "properties": {
      "ip_whitelist": {
        "type": "ip_range"
      }
    }
  }
}
# 插入一个192.168.*.*都支持的白名单文档
PUT /range_index2/_doc/1
{
  "ip_whitelist" : "192.168.0.0/16"
}
# 查询 192.168.1.2是否有匹配的文档: 有
GET /range_index2/_search
{
  "query":{
    "term":{
      "ip_whitelist":"192.168.1.2"
    }
  }
}
# 查询 10.0.1.2是否有匹配的文档: 无
GET /range_index2/_search
{
  "query":{
    "term":{
      "ip_whitelist":"10.0.1.2"
    }
  }
}

9、Nested

  1. 嵌套类型,是object中的一个特例
  2. 可以让array类型的Objects独立索引和查询

9.1、array类型的object 的扁平化

ES没有内部对象(inner objects)的概念,它将对象层次结构平铺为键和值的简单列表,比如下面的文档:

DELETE /my_index
# 不定义索引的mapping,直接插入array类型的数据,ES会自动生成mapping,但是字段类型是object
PUT /my_index/_doc/1
{
  "group" : "fans",
  "user" : [
    {
      "first" : "John",
      "last" :  "Smith"
    },
    {
      "first" : "Alice",
      "last" :  "White"
    }
  ]
}

上面的文档会被平铺成这样:


{
  "group" :        "fans",
  "user.first" : [ "alice", "john" ],
  "user.last" :  [ "smith", "white" ]
}

user.first和user.last会被平铺为多值字段,Alice和White之间的关联关系会消失。上面的文档会被错误的匹配到以下查询(虽然能搜索到,实际上不存在Alice Smith)

# 查询结果是错误的,实际上目前这个索引不存在Alice Smith
GET my_index/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": { "user.first": "Alice" }},
        { "match": { "user.last":  "Smith" }}
      ]
    }
  }
}

9.2、使用 nested 字段类型来处理数组类型的object带来的问题

DELETE /my_index

# 定义索引,使用nested字段类型处理object array
PUT my_index
{
  "mappings": {
    "properties": {
      "user": {
        "type": "nested" 
      }
    }
  }
}

# 插入数据
PUT my_index/_doc/1
{
  "group" : "fans",
  "user" : [
    {
      "first" : "John",
      "last" :  "Smith"
    },
    {
      "first" : "Alice",
      "last" :  "White"
    }
  ]
}

# 搜索 Alice Smith
GET my_index/_search
{
  "query": {
    "nested": {
      "path": "user",
      "query": {
        "bool": {
          "must": [
            { "match": { "user.first": "Alice" }},
            { "match": { "user.last":  "Smith" }}
          ]
        }
      }
    }
  }
}

# 搜索 Alice Smith, 并用inner_hits高亮指定的字段
GET my_index/_search
{
  "query": {
    "nested": {
      "path": "user",
      "query": {
        "bool": {
          "must": [
            { "match": { "user.first": "Alice" }},
            { "match": { "user.last":  "White" }} 
          ]
        }
      },
      "inner_hits": { 
        "highlight": {
          "fields": {
            "user.first": {}
          }
        }
      }
    }
  }
}

9.3、使用限制

ES把每一个nested对象都索引成一个单独的Lucene文档。如果我们要索引一个包含100个user对象的文档,ES会建立101个Lucene文档:一个父级文档,以及100个user对象的文档。因为这个高昂的代价,ES设置了几个参数以防止性能问题。

  1. index.mapping.nested_fields.limit:
    1. 一个索引中独立的nested mappings的最大数量
    2. 默认:50
    3. 只有当需要关联查询array类型的object的时候才使用它,其他情况不要滥用
  2. index.mapping.nested_objects.limit:
    1. 一个单独的文档中所有nested类型字段所包含的nested JSON对象的最大个数
    2. 默认10000:
    3. 有助于阻止OOM(out of memory)问题.

10、TokenCount

  1. 一个token_count 字段 其实 就是一个 integer字段
  2. 可以 存储字符串值
  3. 可以 分析并统计词的个数。
DELETE /my_index
 
# name 字段是text类型
# name.length 是一个 multi filed 的 token_count 类型, 参数 analyzer 必填
PUT /my_index
{
  "mappings": {
    "properties": {
      "name": { 
        "type": "text",
        "fields": {
          "length": {
            "type": "token_count",
            "analyzer": "standard"
          }
        }
      }
    }
  }
}
 
# 插入2个文档
PUT my_index/_doc/1
{ "name": "John Smith" }
PUT my_index/_doc/2
{ "name": "Rachel Alice Williams" }
 
# 查询name字段中词的个数为3的文档
GET my_index/_search
{
  "query": {
    "term": {
      "name.length": 3
    }
  }
}

11、Geo point / Geo shape 类型

11.1、geo point

  1. 接受 纬度-精度 数值对
  2. 使用场景
    1. 在指定的矩形框(geo_bounding_box),或 与某一个坐标一定距离内,或一个多边形,或 地理位置形状查询(geo_shape query),去寻找坐标点
    2. 按地理位置或与某一个位置的距离去聚合文档
    3. 把距离整合到文档的相关性得分中
    4. 把文档按距离排序

11.1.1、设置geo_point的字段的值

DELETE /my_index

# 定义索引
PUT my_index
{
  "mappings": {
    "properties": {
      "location": {
        "type": "geo_point"
      }
    }
  }
}

# 插入geo_point字段的5种方式
PUT my_index/_doc/1
{
  "text": "Geo-point as an object",
  "location": { "lat": 41.12, "lon": -71.34 }
}

# string方式: lat, lon
PUT my_index/_doc/2
{
  "text": "Geo-point as a string",
  "location": "41.12,-71.34"
}

PUT my_index/_doc/3
{
  "text": "Geo-point as a geohash",
  "location": "drm3btev3e86"
}

# 数组方式: lon, lat
PUT my_index/_doc/4
{
  "text": "Geo-point as an array",
  "location": [ -71.34, 41.12 ]
}

PUT my_index/_doc/5
{
  "text": "Geo-point as a WKT POINT primitive",
  "location" : "POINT (-71.34 41.12)"
}
  1. 注意: string方式的顺序是 “lat, lon”,而数组方式的顺序是 [lon, lat]
  2. 参数
    1. ignore_malformed:
      1. 是否忽略不符合要求的值
      2. false(默认):会抛出异常并拒绝接受该文档
      3. true:忽略该位置
    2. null_value
      1. 是否接受一个null值
      2. 默认:null,表示这个字段没有设置
    3. ignore_z_value
      1. 是否接受一个三维坐标值(但是仅纬度和经度会被索引)
      2. true(默认):
      3. false:数据不符合要求时直接抛出异常,并拒绝接受该文档。

11.1.2、查询

# 查询: 按矩形范围
GET my_index/_search
{
  "query": {
    "geo_bounding_box": { 
      "location": {
        "top_left": {
          "lat": 42, "lon": -72
        },
        "bottom_right": {
          "lat": 40, "lon": -74
        }
      }
    }
  }
}


11.2、geo shape

  1. geo_shape数据类型有助于对任意地理形状(如矩形和多边形)进行索引和搜索。
  2. 当被索引的数据或正在执行的查询包含形状而不仅仅是点时,应该使用它,以得到比geo_point更高的查询效率。

11.2.1、mapping选项

  1. orientation:可选,定义如何解释多边形/多多边形的顶点顺序。
  2. ignore_malformed :是否忽略不符合 GeoJSON或WKT形状的数据。
    1. false(默认):如果数据不符合会抛出异常并拒绝该文档。
  3. ignore_z_value
    1. 是否接受三维坐标但是值去经纬度的数据而忽略第三维度的值
    2. true(默认):
    3. false:抛出异常并拒绝该文档。
  4. coerce:是否自动闭合多边形中未闭合的线性环。
    1. false(默认)

12、Date_Nanos

date类型支持到毫秒,如果特殊情况下用到纳秒得用date_nanos类型。


#创建一个index,其date字段是date_nanos类型,支持纳秒
PUT my_index?include_type_name=true
{
  "mappings": {
    "_doc": {
      "properties": {
        "date": {
          "type": "date_nanos" 
        }
      }
    }
  }
}


#和普通的date类型一样,可以存strict_date_optional_time||epoch_millis这些格式的
# 在es内部,会以纳秒为单位的long类型存储
PUT my_index/_doc/1
{ "date": "2015-01-01" } 


# 存一个具体到纳秒的值
PUT my_index/_doc/2
{ "date": "2015-01-01T12:10:30.123456789Z" } 


#存的是整型,说明是秒,换成日期就是2015/1/1 8:0:0
#但是在es内部,会以纳秒为单位的long类型存储
PUT my_index/_doc/3
{ "date": 1420070400 } 

GET my_index/_search
{
  "sort": { "date": "asc"} 
}

13、Boolean

  1. false值:false,“false”,“”
  2. true值:true,“true”
PUT my-index
{
  "mappings": {
    "properties": {
      "is_published": {
        "type": "boolean"
      }
    }
  }
}
 
 
 
POST my-index/_doc/1?refresh
{
  "is_published": "true"
}
 

GET my-index/_search
{
  "query": {
    "term": {
      "is_published": true
    }
  }
}

14、Percolator 111

15、Flattened

  1. 扁平化数据类型,针对json对象

15.1、介绍

默认情况下,JSON对象 中的每个子字段都需要分别进行映射和索引。如果事先不知道 子字段 的名称或类型,则将动态映射它们。由于大量不同的字段映射,会导致映射爆炸。

Flattened 就是来解决这个问题的,flattened 提供了一种替代方法,其中将整个对象映射为单个字段。对于给定的对象,flatten类型映射 将解析出其 leaf(叶子节点)值,并将它们作为关键字索引到一个字段中。然后可以通过简单的查询和汇总来搜索对象的内容。

15.2、缺点

flatten 的对象字段在搜索功能方面存在折衷。仅允许基本查询,不支持数字范围查询或突出显示(highlighting)。

15.3、注意

flattened 不应用于 索引所有文档内容,因为它将所有值都视为关键字,并且不提供完整的搜索功能。在大多数情况下,默认方法(每个子字段在映射中都有其自己相对应的项)有效。

15.4、案例

15.4.1、创建一个 my_index 的索引及它的 mapping

PUT my_index
{
  "mappings": {
    "properties": {
      "title": {
        "type": "text"
      },
      "labels": {
        "type": "flattened"
      }
    }
  }
}

我们定义 labels 的数据类型为 flattened,意味着这个字段可以用来保持一个对象。

15.4.2、插入数据

POST my_index/_doc/1
{
  "title": "Results are not sorted correctly.",
  "labels": {
    "priority": "urgent",
    "release": [
      "v1.2.5",
      "v1.3.0"
    ],
    "timestamp": {
      "created": 1541458026,
      "closed": 1541457010
    }
  }
}

在上面我们可以看出来:

  1. labels 是一个对象,它包含 priority,release 及 timestamp的leaf项。
  2. 在建立索引的时候,Elasticsearch 为 JSON 对象的每一个 leaf 值建立 token,这些值被索引为字符串关键字,无需对数字或日期进行特殊处理。针对我们的情况,Elasticsearch 在建立索引时,会对 urgent,v1.2.5, v1.3.0, 1541458026 及1541457010 建立 token,并供我们进行搜索。

15.4.3、查询–对priority属性进行查询

POST my_index/_search
{
  "query": {
    "term": {
      "labels": "urgent"
    }
  }
}

查询的结果是:

  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 0.42763555,
    "hits" : [
      {
        "_index" : "my_index",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 0.42763555,
        "_source" : {
          "title" : "Results are not sorted correctly.",
          "labels" : {
            "priority" : "urgent",
            "release" : [
              "v1.2.5",
              "v1.3.0"
            ],
            "timestamp" : {
              "created" : 1541458026,
              "closed" : 1541457010
            }
          }
        }
      }
    ]
  }

15.4.4、查询–对数字 进行查询

POST my_index/_search
{
  "query": {
    "term": {
      "labels": 1541458026
    }
  }
}

查询的结果是:

  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 0.42763555,
    "hits" : [
      {
        "_index" : "my_index",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 0.42763555,
        "_source" : {
          "title" : "Results are not sorted correctly.",
          "labels" : {
            "priority" : "urgent",
            "release" : [
              "v1.2.5",
              "v1.3.0"
            ],
            "timestamp" : {
              "created" : 1541458026,
              "closed" : 1541457010
            }
          }
        }
      }
    ]
  }

15.4.5、查询–对指定属性查询

要查询 flattened 对象中的特定键,使用 “.” 来表示

POST my_index/_search
{
  "query": {
    "term": {
      "labels.release": "v1.3.0"
    }
  }
}

查询的结果是:

  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 0.42763555,
    "hits" : [
      {
        "_index" : "my_index",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 0.42763555,
        "_source" : {
          "title" : "Results are not sorted correctly.",
          "labels" : {
            "priority" : "urgent",
            "release" : [
              "v1.2.5",
              "v1.3.0"
            ],
            "timestamp" : {
              "created" : 1541458026,
              "closed" : 1541457010
            }
          }
        }
      }
    ]
  }

15.5、支持的操作

  1. 由于索引值的方式相似,flattened字段 与 keyword字段 共享许多相同的映射和搜索功能,这是因为它们在建立索引时的方式非常相似。
  2. flattened的对象字段可以与以下查询类型一起使用:
    1. term,terms,and terms_set
    2. prefix
    3. range
    4. match and multi_match
    5. query_string and simple_query_string
    6. exists
  3. 查询时,不能使用通配符来引用字段关键字,例如 {“term”:{“labels.time *”:1541457010}}。
  4. 注意:所有查询(包括范围)都将值视为字符串关键字。拼合的字段不支持突出显示(highlighting)。
  5. 可以对 flattened 的对象字段进行排序,以及执行简单的关键字样式聚合(例如terms aggregation)。 与查询一样,对数字没有特殊支持,将 JSON 对象中的所有值都视为关键字。 排序时,这意味着按字典顺序对值进行比较。
  6. flattened的对象字段 当前无法存储,无法在映射中指定 store 参数。

16、Rank_Feature 111

排名功能查询相关

17、Rank_Features 111

排名功能查询相关

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值