TrumanWong

Elasticsearch字段类型

TrumanWong
3/21/2022

常用类型

binary

binary定义的字段类型可以存储编码为Base64的字符串或二进制值。范例如下:

# 创建索引映射并指定blob字段的类型为二进制类型
PUT myindex
{
  "mappings": {
    "properties": {
      "name": {
        "type": "text"
      },
      "blob": {
        "type": "binary"
      }
    }
  }
}

# 在索引库中插入数据,blob的内容是Base64编码的字符串
PUT myindex/_doc/1
{
  "name": "Some binary blob",
  "blob": "SGVsbG8gd29yZA"
}

boolean

表示可以存储truefalse的布尔值,也可以存储truefalse的字符串。范例如下:

# 创建索引映射并指定is_published字段为bool类型
PUT myindex
{
  "mappings": {
    "properties": {
      "is_published": {
        "type": "boolean"
      }
    }
  }
}

# 新增数据字段类型必须和映射类型匹配
PUT myindex/_doc/1
{
  "is_published": "true"
}

# 查询索引库中is_published字段
GET myindex/_search
{
  "query": {
    "term": {
      "is_published": true
    }
  }
}

查询结果如下图所示:

TrumanWong

在使用布尔类型字段时需要注意的是,布尔类型的查询不能使用0或1替代,否则会抛出异常。如下图所示:

TrumanWong

可以看到,使用1作为筛选值进行查询时不能正确地转换为bool类型的值。如果需要对布尔值进行转换,可以使用“运行时”脚本来处理,范例如下:

GET myindex/_search
{
  "fields": [
    "weight"
  ],
  "runtime_mappings": {
    "weight": {
      "type": "long",
      "script": {
        "source": "emit(doc['is_published'].value ? 1 : 0)"
      }
    }
  }
}

结果如下图所示:

TrumanWong

keyword

该字段类型的数据在存储时不会进行分词处理,适合进行统计分析,不能进行全文搜索,通常用于排序、聚合查询等。范例如下:

# 创建索引映射并指定tag字段的字段类型为keyword类型
PUT myindex
{
  "mappings": {
    "properties": {
      "tag": {
        "type": "keyword"
      }
    }
  }
}

# 插入文档数据
PUT myindex/_doc/1
{
  "tag": "北京"
}

# 插入文档数据
PUT myindex/_doc/2
{
  "tag": "北京人"
}

# 查询索引库中tag字段是“北京”且完全匹配的内容
GET myindex/_search
{
  "query": {
    "term": {
      "tag": {
        "value": "北京"
      }
    }
  }
}

返回结果如下所示:

TrumanWong

以上语句返回了tag字段中内容完全匹配的文档,在查询过程中不会对查询的字段内容进行分词。

text

该字段类型的数据在存储时会进行分词并建立索引,适合进行全文搜索,不能进行统计分析。

text类型用于进行全文搜索(也成为全文检索),例如电子邮件正文或产品描述的全文,它们在被搜索之前通过分词器将全部文字内容转换为单词(term)表。text类型允许用户在每个全文字段中搜索单个单词。text类型的字段不适合进行排序,也不适合进行聚合计算。如果字段需要聚合计算或者排序,推荐使用keyword类型。需要特别注意的是,keyword类型和text类型区别是:keyword类型的字段内容不会被分词,text类型的字段内容会被分词。范例如下:

# 创建索引映射并指定tagname字段的字段类型为text类型
PUT myindex
{
  "mappings": {
    "properties": {
      "tagname": {
        "type": "text"
      }
    }
  }
}

# 插入文档数据
PUT myindex/_doc/1
{
  "tagname": "江苏省"
}

# 插入文档数据
PUT myindex/_doc/2
{
  "tagname": "河北省"
}

# 根据tagname字段内容分词,然后对所有分词内容进行匹配
GET myindex/_search
{
  "query": {
    "match": {
      "tagname": "河南省"
    }
  }
}

返回结果如下:

TrumanWong

以上搜索结果中把“江苏省”和“河北省”这两行数据都返回了,这是因为目前默认的分词器把“河南省”分成了“河南”和“省”两个字,而“河北省”和“江苏省”分别分成“河北”、“省”和“江苏”、“省”,这两个词被分词后都有一个“省”字,所以搜索时被全文匹配到了。在实际业务中,如果我们要对字段的内容进行全文搜索,可以使用text类型;如果要聚合查询或者精准匹配,则尽量使用keyword类型。

对于大多数想要对文本字段执行更多操作的用户,也可以使用多字段映射,其中既有text类型可以用于全文搜索,又有keyword类型可以用于聚合分析,语法如下:

PUT 索引库名称
{
  "mappings": {
    "properties": {
      "my_field": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword"
          }
        }
      }
    }
  }
}

由以上语句可知,my_field字段的映射关系是:父字段类型是text类型,子字段类型是keyword类型。范例如下:

# 创建索引映射
PUT myindex
{
  "mappings": {
    "properties": {
      "tagname": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword"
          }
        }
      }
    }
  }
}

# 插入文档数据
PUT myindex/_doc/1
{
  "tagname": "江苏省"
}

# 插入文档数据
PUT myindex/_doc/2
{
  "tagname": "河北省"
}

# 根据父字段(text类型)搜索符合要求的文档数据
GET myindex/_doc/_search
{
  "query": {
    "match": {
      "tagname": "河南省"
    }
  }
}

返回结果如下:

TrumanWong

其中,使用tagname字段的父字段(text类型)进行搜索,因为父字段是text类型,所以搜索时会进行分词。结果返回了包含“江苏省”和“河北省”的文档信息。如果要利用tagname字段的子字段(keyword类型)进行匹配查询,则应该使用如下语句:

GET myindex/_search
{
  "query": {
    "match": {
      "tagname.keyword": "河南省"
    }
  }
}

其中,tagname.keyword代表使用了tagname字段的子字段(keyword类型)进行不分词搜索,结果如下图所示:

TrumanWong

因为以上语句是进行不分词的搜索,需要保证搜索的内容和字段存储的内容完全匹配,所以从当前索引库中没有匹配到任何文档数据。

numbers

用于表示数字类型。Elasticsearch支持多种数字类型,每种数字类型的取值范围参考下表:

数字类型 说明
long 表示有符号的64位整数,范围为-263~263-1
integer 表示有符号的32位整数,范围为-231~231-1
short 表示有符号的16位整数,范围为-32768~32767
byte 表示有符号的8位整数,范围为-128~127
double 表示双精度浮点数,范围为2-1074~(2-2-52)*21023
float 表示单精度浮点数,范围为2-149~(2-2-23)*2127
half_float 表示可以存储范围为2-24~65504的数值
unsigned_long 表示可以存储范围为0~264-1的数值

范例如下:

# 创建索引并创建字段映射关系
PUT myindex
{
  "mappings": {
    "properties": {
      "number": {
        "type": "integer"
      },
      "time_in_seconds": {
        "type": "float"
      },
      "price": {
        "type": "scaled_float",
        "scaling_factor": 100
      }
    }
  }
}

# 插入文档数据
PUT myindex/_doc/1
{
  "number": 1,
  "time_in_seconds": 1.001,
  "price": 1.11
}

在以上语句创建的索引映射中,scaling_factor参数表示数值在存储时使用了缩放因子,该值在存储时乘以缩放因子并四舍五入到最接近long类型的值(比如1.11实际存储的是111)。注意,这个参数时必不可少的。

就上面范例中数字类型而言,它们可以存储任何数字,但是我们在使用时尽量选择可以满足需求的最小数值类型,这样可以更有效编制索引和进行搜索,同时也可以节省一部分的存储空间。

date

表示可以存储日期类型的数据。Elasticsearch中的日期类型可以是包含日期格式的字符串,例如“2022-01-01”或“2022/01/01 00:00:00”等格式,也可以使用自纪元以来的毫秒数来表示(注:在Unix中,纪元是指UTC时间1970年1月1日00:00:00)。范例如下:

# 创建索引映射并指定date字段的类型为日期类型
PUT myindex
{
  "mappings": {
    "properties": {
      "date": {
        "type": "date"
      }
    }
  }
}

# 插入文档数据
PUT myindex/_doc/1
{
  "date": "2022-03-19"
}

PUT myindex/_doc/2
{
  "date": "2022-03-19T12:10:30Z"
}

PUT myindex/_doc/3
{
  "date": "1647619200"
}

以上三种不同格式的日期数据都被插入到索引库中。如果想指定存储的日期格式,则可以通过下面的语句来创建映射:

# 创建索引映射并指定date字段的类型为日期类型
PUT myindex
{
  "mappings": {
    "properties": {
      "date": {
        "type": "date",
        "format": "yyyy-MM-dd HH🇲🇲ss"
      }
    }
  }
}

# 以下语句插入会抛出异常,因为日期内容不符合映射格式
PUT myindex/_doc/1
{
  "date": "2022-03-19"
}

# 以下语句插入会抛出异常,因为日期内容不符合映射格式
PUT myindex/_doc/2
{
  "date": "2022-03-19T12:10:30Z"
}

# 以下语句插入会抛出异常,因为日期内容不符合映射格式
PUT myindex/_doc/3
{
  "date": "1647619200"
}

# 以下语句可正常插入,因为日期内容符合字段指定的日期格式
PUT myindex/_doc/4
{
  "date": "2022-03-19 00:00:00"
}

alias

alias(别名)类型可以为索引中的字段定义一个替代名称。范例如下:

# 创建名为userinfo的索引库并为其创建映射关系
PUT userinfo
{
  "mappings": {
    "properties": {
      "age": {
        "type": "long"
      },
      "aliasage": {
        "type": "alias",
        "path": "age"
      },
      "transit_mode": {
        "type": "keyword"
      }
    }
  }
}

# 在索引库userinfo中插入一条文档数据
PUT userinfo/_doc/1
{
  "age": 26,
  "transit_mode": "transit_mode"
}

# 通过别名查询年龄大于20的用户信息
GET userinfo/_doc/_search
{
  "query": {
    "rage": {
      "aliasage": {
        "gt": 30
      }
    }
  }
}

在使用alias时需要注意的是,可以使用别名进行数据的搜索,但是不能使用别名进行数据的写入。如下图所示:

TrumanWong

对象和关系类型

object

Elasticsearch中的object类型实际就是JSON数据格式,范例如下:

# 创建索引映射
PUT myindex
{
  "mappings": {
    "properties": {
      "region": {
        "type": "keyword"
      },
      "manager": {
        "properties": {
          "age": {
            "type": "integer"
          },
          "name": {
            "properties": {
              "first": {
                "type": "text"
              },
              "last": {
                "type": "text"
              }
            }
          }
        }
      }
    }
  }
}

manager是一个对象,该对象中又包含一个name对象,而name对象中又有两个键值对。如果需要向这个索引映射中插入文档,可以使用下面任何一种方式写入数据:

  • 使用嵌套的JSON数据格式进行写入

    PUT myindex/_doc/1
    {
      "region": "Argentina",
      "manager": {
        "age": 30,
        "name": {
          "first": "Lionel",
          "last": "Messi"
        }
      }
    }
    
  • 使用简单的JSON数据格式进行写入

    PUT myindex/_doc/2
    {
      "region": "Uruguay",
      "manager.age": "30",
      "manager.name.first": "Luis",
      "manager.name.last": "Suárez"
    }
    

使用以上两种方式写入数据不会影响数据的存储,但是会影响查询返回的结果。查询结果如下所示:

TrumanWong

可以看到,查询返回的格式与写入格式一致。

nested

nested(嵌套)类型是object数据类型的特殊版本,可以在对象中嵌套对象或在字段中存储键值对Key-Value Pair。范例如下:

# 创建索引映射并指定user字段为一个嵌套类型
PUT myindex
{
  "mappings": {
    "properties": {
      "user": {
        "type": "nested"
      }
    }
  }
}

# 在索引库中插入文档数据,user字段中嵌套了键值对
PUT myindex/_doc/1
{
  "group": "fans",
  "user": [
    {
      "first": "Lionel",
      "last": "Messi"
    },
    {
      "first": "Luis",
      "last": "Suárez"
    }
  ]
}

由以上语句可知,user字段内容中嵌套了两个键值对。

# 查询user索引库字段中user.first的值时Lionel以及user.last的值时Suárez的结果
GET myindex/_search
{
  "query": {
    "nested": {
      "path": "user",
      "query": {
        "bool": {
          "must": [
            {
              "match": {
                "user.first": "Lionel"
              }
            },
            {
              "match": {
                "user.last": "Suárez"
              }
            }
          ]
        }
      }
    }
  }
}

以上查询语句中需要注意的是,利用嵌套字段进行筛选查询时,必须所有字段值都要符合条件,如果其中一个字段不满足查询条件,则从索引库中查询不到任何数据。执行结果如下所示:

TrumanWong

array

Elasticsearch种,没有专用的数组数据类型。默认情况下,任何字段都可以包含0个或多个值,但是数组中的所有值必须具有相同的字段类型。范例如下:

# 在索引库中插入一条文档数据
PUT myindex/_doc/1
{
  "message": "some arraysin this document...",
  "tags": ["Elasticsearch", "wow"],
  "lists": [
    {
      "name": "prog_list",
      "description": "programming list"
    },
    {
      "name": "cool_list",
      "description": "cool stuff list"
    }
  ]
}

# 再次往索引库插入数据,tags的类型必须是字符串类型,或者包含多个字符串元素的数组。
PUT myindex/_doc/2
{
  "message": "no arrays in this document...",
  "tags": "Elasticsearch",
  "lists": {
    "name": "prog_list",
    "description": "programming_list"
  }
}

# 查询索引库中tags字段中包含Elasticserach字符的元素
GET myindex/_search
{
  "query": {
    "match": {
      "tags": "Elasticsearch"
    }
  }
}

从查询结果可以看到,包含Elasticsearch字符串结果的文档共有两条记录,说明数组字段类型的操作符合其定义说明。只要保证插入的数组字段中的数据类型是同一个类型,就能把数据写入此数组字段中。

TrumanWong

其余类型

range

range(范围)类型表示介于上限和下限之间的连续值范围,可以使用运算符gt(大于)、gte(大于等于)、lt(小于)、lte(小于等于)定义存储文档的数据范围。每一种范围类型的说明如下表所示:

范围类型 说明
integer_range 表示有符号的32位整数
float_range 表示单精度浮点数
long_range 表示有符号的64位整数
double_range 表示双精度浮点数
date_range 表示日期范围,可以通过format映射参数支持各种日期格式。无论使用哪种格式,日期值都会被解析为一个无符号的64位整数,该整数位纪元以来的毫秒数
ip_range 表示IPv4IPv6地址的一系列IP

范例如下:

# 创建索引映射,并指定expected_attendees字段类型位整数范围类型,time_frame字段类型位日期范围类型
PUT myindex
{
  "mappings": {
    "properties": {
      "expected_attendees": {
        "type": "integer_range"
      },
      "time_frame": {
        "type": "date_range",
        "format": "yyyy-MM-dd HH🇲🇲ss"
      }
    }
  }
}

# 插入文档数据
PUT myindex/_doc/1
{
  "expected_attendees": {
    "gte": 10,
    "lt": 20
  },
  "time_frame": {
    "gte": "2022-01-01 12:00:00",
    "lte": "2022-03-20 15:00:00"
  }
}

# 查询满足expected_attendees字段中数据范围内包括12的文档数据
GET myindex/_search
{
  "query": {
    "term": {
      "expected_attendees": {
        "value": 12
      }
    }
  }
}

# 根据日期范围查询符合条件的文档数据
GET myindex/_search
{
  "query": {
    "range": {
      "time_frame": {
        "gte": "2022-01-01 12:00:00",
        "lte": "2022-03-20 15:00:00",
        "relation": "within"
      }
    }
  }
}

查询结果如下所示。可以看出,只要范围类型字段的内容包含在筛选的范围内,就会返回当前文档的内容。

TrumanWong

TrumanWong

rank_feature

rank_feature(排名)类型的字段可以存储数字,并且队搜索文档的分数有所影响(搜索文档的分数就是用户搜索的内容和搜索返回文档的匹配度,分数越高,就表示匹配度越高)。范例如下:

# 创建索引映射并将”pagerank“和”topics“两个字段类型分别指定为”rank_feature“类型和”rank_features“类型
PUT myindex
{
  "mappings": {
    "properties": {
      "pagerank": {
        "type": "rank_feature"
      },
      "url_length": {
        "type": "rank_feature",
        "positive_score_impact": false
      },
      "topics": {
        "type": "rank_features"
      }
    }
  }
}

#在索引库中插入数据
PUT myindex/_doc/1
{
  "url": "https://en.wikipedia.org/wiki/2016_Summer_Olympics",
  "content": "Rio 2016",
  "pagerank": 50.3,
  "url_length": 42,
  "topics": {
    "sports": 50,
    "brazil": 30
  }
}
#在索引库中插入数据
PUT myindex/_doc/2
{
  "url": "https://en.wikipedia.org/wiki/2016_Brazilian_Grand_Prix",
  "content": "Formula One motor race held on 13 November 2016 at the Autódromo José Carlos Pace in São Paulo, Brazil",
  "pagerank": 50.3,
  "url_length": 47,
  "topics": {
    "sports": 35,
    "formula one": 65,
    "brazil": 20
  }
}
#在索引库中插入数据
PUT myindex/_doc/3
{
  "url": "https://en.wikipedia.org/wiki/Deadpool_(film)",
  "content": "Deadpool is a 2016 American superhero film",
  "pagerank": 50.3,
  "url_length": 37,
  "topics": {
    "movies": 60,
    "super hero": 65
  }
}
     
#查询索引库的content字段值中包含"2016"的文档,并根据评分(score字段的值)排序输出
GET myindex/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "content": "2016"
          }
        }
      ],
      "should": [
        {
          "rank_feature": {
            "field": "pagerank"
          }
        },
        {
          "rank_feature": {
            "field": "url_length",
            "boost": 0.1
          }
        },
        {
          "rank_feature": {
            "field": "topics.sports",
            "boost": 0.4
          }
        }
      ]
    }
  }
} 

查询结果如下:

{
  "took" : 62,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 3,
      "relation" : "eq"
    },
    "max_score" : 0.9628078,
    "hits" : [
      {
        "_index" : "myindex",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 0.9628078,
        "_source" : {
          "url" : "https://en.wikipedia.org/wiki/2016_Summer_Olympics",
          "content" : "Rio 2016",
          "pagerank" : 50.3,
          "url_length" : 42,
          "topics" : {
            "sports" : 50,
            "brazil" : 30
          }
        }
      },
      {
        "_index" : "myindex",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 0.82140046,
        "_source" : {
          "url" : "https://en.wikipedia.org/wiki/2016_Brazilian_Grand_Prix",
          "content" : "Formula One motor race held on 13 November 2016 at the Autódromo José Carlos Pace in São Paulo, Brazil",
          "pagerank" : 50.3,
          "url_length" : 47,
          "topics" : {
            "sports" : 35,
            "formula one" : 65,
            "brazil" : 20
          }
        }
      },
      {
        "_index" : "myindex",
        "_type" : "_doc",
        "_id" : "3",
        "_score" : 0.7016779,
        "_source" : {
          "url" : "https://en.wikipedia.org/wiki/Deadpool_(film)",
          "content" : "Deadpool is a 2016 American superhero film",
          "pagerank" : 50.3,
          "url_length" : 37,
          "topics" : {
            "movies" : 60,
            "super hero" : 65
          }
        }
      }
    ]
  }
}

由以上语句可知,rank_feature字段类型和rank_features字段类型只能搭配rank_feature参数查询。

token_count

token_count(令牌计数)类型的字段实际上是一个integer类型的字段,它可以队内容进行分词分析,存储内容被分词的数量。范例如下:

# 创建索引映射,给name字段添加子对象,其名称是length,类型是token_count,使用standard分词期进行分词
PUT myindex
{
  "mappings": {
    "properties": {
      "name": {
        "type": "text",
        "fields": {
          "length": {
            "type": "token_count",
            "analyzer": "standard"
          }
        }
      }
    }
  }
}

# 添加文档数据
PUT myindex/_doc/1
{
  "name": "Lionel Messi"
}

# 添加文档数据
PUT myindex/_doc/2
{
  "name": "Luis Suárez"
}

PUT myindex/_doc/3
{
  "name": "Barack Hussein Obama II"
}

# 查询索引库中name字段被分词后,分词数量等于2的文档
GET myindex/_search
{
  "query": {
    "term": {
      "name.length": 2
    }
  }
}

TrumanWong

可以看到”Lionel Messi“被standard分词分为”Lionel“和”Messi“,所以分词数量是2。上面的返回结果符合预期。在查询过程中,我们还可以使用分析语句对查询的内容进行预判分析,范例如下:

# 使用standard分词器对内容”Lionel Messi“进行分词处理,返回分词后的结果
GET myindex/_analyze
{
  "analyzer": "standard",
  "text": ["Lionel Messi"]
}

返回结果如下图所示:

TrumanWong

以上结果与我们预想的一样,”Lionel Messi“被分词成两个单词,还记录了具体分词的单词在原始内容中的偏移量。

ip

ip类型字段可以用于存储IPv4IPv6地址。范例如下:

# 创建索引映射并指定ip_addr字段的类型为ip类型
PUT myindex
{
  "mappings": {
    "properties": {
      "ip_addr": {
        "type": "ip"
      }
    }
  }
}

# 插入文档数据
PUT myindex/_doc/1
{
  "ip_addr": "192.168.1.1"
}

# 插入文档数据
PUT myindex/_doc/2
{
  "ip_addr": "192.168.1.2"
}

# 查询IP地址是“192.168.1.1”的文档数据
GET myindex/_search
{
  "query": {
    "term": {
      "ip_addr": "192.168.1.1"
    }
  }
}

返回结果如下:

TrumanWong

由以上语句可知,返回的文档数据信息与筛选内容一致。值得一提的是,ip类型也支持IP地址的范围查询。范例如下:

# 查询IP地址符合“192.168.1.0/16”范围的文档数据
GET myindex/_search
{
  "query": {
    "term": {
      "ip_addr": "192.168.1.0/16"
    }
  }
}

返回结果如下:

TrumanWong

geo_point

用于地理位置的存储与搜索类型。使用语法如下:

PUT 索引库名称
{
    ”mappings“: {
        "properties": {
            "location": {
                "type": "geo_point"
            }
        }
    }
}

范例如下:

# 创建索引映射并指定location字段的字段类型为geo_point类型
PUT myindex
{
  "mappings": {
    "properties": {
        "name": {
        "type": "text"
      },
      "location": {
        "type": "geo_point"
      }
    }
  }
}

# 插入酒店相关数据
PUT myindex/_doc/1
{
  "name": "XX酒店",
  "location": {
    "lat": 22.18,
    "lon": 118.34
  }
}

# 搜索指定的两个地理位置形成的矩形范围中包含的酒店信息
GET myindex/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match_all": {}
        }
      ],
      "filter": [
        {
          "geo_bounding_box": {
            "location": {
              "top_left": {
                "lat": 22.73,
                "lon": 118.1
              },
              "bottom_right": {
                "lat": 21.717,
                "lon": 118.99
              }
            }
          }
        }
      ]
    }
  }
}

# 搜索指定的多个地理位置形成的多边形范围中包含的酒店信息
GET myindex/_search
{
  "query": {
    "bool": {
      "must": [
        {"match_all": {}}
      ],
      "filter": [
        {
          "geo_polygon": {
            "location": {
              "points": [
                {
                  "lat": 22.73,
                  "lon": 118.1
                },
                {
                  "lat": 21.717,
                  "lon": 118.99
                },
                {
                  "lat": 30.20,
                  "lon": 130
                }
              ]
            }
          }
        }
      ]
    }
  }
}

# 搜索指定位置1000km范围内的酒店数据
GET myindex/_search
{
  "query": {
    "bool": {
      "must": [
        {"match_all": {}}
      ],
      "filter": [
        {
          "geo_distance": {
            "distance": "1000km",
            "location": {
              "lat": 22.1,
              "lon": 118
            }
          }
        }
      ]
    }
  }
}

# 搜索距离指定位置一定范围内有多少个酒店
GET myindex/_search
{
  "size": 0,
  "aggs": {
    "count_by_distinct": {
      "geo_distance": {
        "field": "location",
        "origin": {
          "lat": 52.376,
          "lon": 4.894
        },
        "ranges": [
          {
            "from": 100,
            "to": 300
          },
          {
            "from": 300
          }
        ],
        "unit": "mi",
        "distance_type": "arc"
      }
    }
  }
}

geo_shape

geo_shape(空间位置)类型支持地理形状的搜索,即支持点、线、圈、多边形搜索等。比如我们想找到最接近给定位置的路线,就可以使用此类型。语法如下:

PUT 索引库名称
{
    "mappings": {
        "properties": {
            "location": {
                "type": "geo_shape"
            }
        }
    }
}

以上语句为索引库创建了geo_shape类型的字段映射。范例如下:

# 创建索引映射并指定location字段的字段类型为geo_shape类型
PUT myindex
{
  "mappings": {
    "properties": {
      "location": {
        "type": "geo_shape"
      }
    }
  }
}

# 插入地点相关信息
PUT myindex/_doc/1
{
  "name": "Wind & Wetter, Berlin, Germany",
  "location": {
    "type": "point",
    "coordinates": [ 13.400544, 52.530286 ]
  }
}

# 搜索指定的两个位置范围内的地点
GET myindex/_search
{
  "query": {
    "bool": {
      "must": [
        {"match_all": {}}
      ],
      "filter": [
        {
          "geo_shape": {
            "location": {
              "shape": {
                "type": "envelope",
                "coordinates": [
                  [
                    13.0,
                    53.0
                  ],
                  [
                    14.0,
                    52.0
                  ]
                ]
              },
              "relation": "within"
            }
          }
        }
      ]
    }
  }
}

查询结果如下:

TrumanWong

search_as_you_type

search_as_you_type字段类型和text字段类型很相似,Elasticsearch对其进行了优化,为用户提供了开箱即用的功能。search_as_you_type字段类型的字段可以创建一系列的子字段,语法如下:

PUT 索引库名称
{
    "mappings": {
        "properties": {
            "field": {
                "type": "search_as_you_type"
            }
        }
    }
}

当执行上面的模板映射时,将会为field字段创建如下表中的所有字段作为其子字段:

创建的字段 说明
field 按照映射中的配置进行分析,如果未配置分析词,则使用索引的默认分词器
field._2gram 用大小为2的shingle token filter分词器对field进行分词
field._3gram 用大小为3的shingle token filter分词器对field进行分词
field._index_prefix edge ngram token filter打包field._3gram的分词器

范例如下:

# 创建索引映射并指定my_field字段的字段类型为search_as_you_type类型
PUT myindex
{
  "mappings": {
    "properties": {
      "my_field": {
        "type": "search_as_you_type"
      }
    }
  }
}

# 插入文档
PUT myindex/_doc/1
{
  "my_field": "quick brown fox jump lazy dog"
}

# 查询索引库,从my_field、my_field._2gram、my_field._3gram字段中筛选,返回内容中包含字符串“brown f”的文档数据
GET myindex/_search
{
  "query": {
    "multi_match": {
      "query": "brown f",
      "type": "bool_prefix",
      "fields": [
        "my_field",
        "my_field._2gram",
        "my_field._3gram"
      ]
    }
  }
}

查询结果如图所示:

TrumanWong

可以看到返回结果符合预期。