本篇文章主要讲解elasticsearch在业务中经常用到的字段类型,通过大量的范例来学习和理解不同字段类型的应用场景。范例elasticsearch使用的版本为7.17.5。
在Elasticsearch的映射关系中,每个字段都对应一个数据类型或者字段类型,这些类型规范了字段存储的值和用途。例如,可以将字符串索引到text和keyword字段。text字段的值用于全文搜索;keyword字段的值存储时不会被分词建立索引,主要用于统计计算等操作。
#建立一个人名索引,设定姓名字段为keyword字段
PUT /user
{
"mappings": {
"properties": {
"user_name": {
"type": "keyword"
}
}
}
}
#插入数据
PUT /user/_doc/001
{
"user_name": "张三"
}
#使用term查询刚刚写入的数据
GET /user/_search
{
"query": {
"term": {
"user_name": {
"value": "张三"
}
}
}
}
#返回的结果如下
{
"took": 0,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 0.2876821,
"hits": [
{
"_index": "user",
"_type": "_doc",
"_id": "001",
"_score": 0.2876821,
"_source": {
"user_name": "张三"
}
}
]
}
}
由搜索结果可以看出,使用term进行全字符串匹配"张三"可以搜索到命中文档。
#使用match查询刚刚写入的数据中带有"张"的记录
GET /user/_search
{
"query": {
"match": {
"user_name": "张"
}
}
}
#返回的结果如下
{
"took": 0,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 0,
"relation": "eq"
},
"max_score": null,
"hits": []
}
}
由搜索结果可以看出,对keyword类型使用match搜索进行匹配是不会命中文档的。
#建立一个hotel索引,可以设定title字段为text字段
PUT /hotel
{
"mappings": {
"properties": {
"title": {
"type": "text"
}
}
}
}
#插入数据
POST /hotel/_doc/001
{
"title":"文雅酒店"
}
#按照普通的term进行搜索
GET /hotel/_search
{
"query": {
"term": {
"title": {
"value": "文雅酒店"
}
}
}
}
#返回的结果如下
{
"took" : 570,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 0,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ ]
}
}
3.使用match查询刚刚写入的数据中带有"文雅"的记录
#按照普通的match进行搜索
GET /hotel/_search
{
"query": {
"match": {
"title": "文雅"
}
}
}
#返回结果如下
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 0.5753642,
"hits" : [
{
"_index" : "hotel",
"_type" : "_doc",
"_id" : "001",
"_score" : 0.5753642,
"_source" : {
"title" : "文雅酒店"
}
}
]
}
}
#创建索引映射并指定tagname字段的字段类型为text类型
PUT myindex-2_13
{
"mappings": {
"properties": {
"tagname": {
"type": "text"
}
}
}
}
#插入文档数据
PUT myindex-2_13/_doc/1
{
"tagname":"江苏省"
}
#插入文档数据
PUT myindex-2_13/_doc/2
{
"tagname":"河北省"
}
#根据tagname字段内容分词,然后对所有分词进行匹配搜索
GET myindex-2_13/_doc/_search
{
"query": {
"match": {
"tagname": "河南省"
}
}
}
#返回的结果如下
{
"took" : 2,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : 0.8754687,
"hits" : [
{
"_index" : "myindex-2_13",
"_type" : "_doc",
"_id" : "2",
"_score" : 0.8754687,
"_source" : {
"tagname" : "河北省"
}
},
{
"_index" : "myindex-2_13",
"_type" : "_doc",
"_id" : "1",
"_score" : 0.18232156,
"_source" : {
"tagname" : "江苏省"
}
}
]
}
}
PUT 索引库名称
{
"mappings": {
"properties": {
"my_field": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword"
}
}
}
}
}
}
#创建索引映射
PUT myindex-2_14
{
"mappings": {
"properties": {
"tagname": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword"
}
}
}
}
}
}
#插入文档数据
PUT myindex-2_14/_doc/1
{
"tagname":"江苏省"
}
#插入文档数据
PUT myindex-2_14/_doc/2
{
"tagname":"河北省"
}
#根据父字段(text类型)搜索符合要求的文档数据
GET myindex-2_14/_doc/_search
{
"query": {
"match": {
"tagname": "河南省"
}
}
}
#返回的结果为
{
"took" : 1029,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : 0.8754687,
"hits" : [
{
"_index" : "myindex-2_14",
"_type" : "_doc",
"_id" : "2",
"_score" : 0.8754687,
"_source" : {
"tagname" : "河北省"
}
},
{
"_index" : "myindex-2_14",
"_type" : "_doc",
"_id" : "1",
"_score" : 0.18232156,
"_source" : {
"tagname" : "江苏省"
}
}
]
}
}
#利用tagname字段的子字段(keyword类型)进行匹配查询
GET myindex-2_14/_search
{
"query": {
"match": {
"tagname.keyword": "江苏省"
}
}
}
#返回结果为
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 0.6931471,
"hits" : [
{
"_index" : "myindex-2_14",
"_type" : "_doc",
"_id" : "1",
"_score" : 0.6931471,
"_source" : {
"tagname" : "江苏省"
}
}
]
}
}
#一个酒店搜索项目,酒店的索引除了包含酒店名称和城市之外,还需要定义价格、星级和评论数等。
PUT /hotel/_mapping
{
"properties": {
"city": {
"type": "keyword"
},
"price": {
"type": "double"
},
"start": {
"type": "byte"
},
"comment_count": {
"type": "integer"
}
}
}
#插入数据
POST /hotel/_doc/001
{
"title":"文雅酒店",
"city":"上海",
"price":270,
"start":10,
"comment_count":2
}
#搜索价格为200~300(包含200和300)的酒店
GET /hotel/_search
{
"query": {
"range": {
"price": {
"gte": 200,
"lte": 300
}
}
}
}
#返回结果如下
{
"took" : 596,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "hotel",
"_type" : "_doc",
"_id" : "001",
"_score" : 1.0,
"_source" : {
"title" : "文雅酒店",
"city" : "上海",
"price" : 270,
"start" : 10,
"comment_count" : 2
}
}
]
}
}
#创建索引并创建字段映射关系
PUT myindex-2_09
{
"mappings": {
"properties": {
"number": {
"type": "integer"
},
"time_in_secondes": {
"type": "float"
},
"price": {
"type": "scaled_float",
"scaling_factor": 100
}
}
}
}
#插入文档数据
PUT myindex-2_09/_doc/1?refresh
{
"number":1,
"time_in_secondes":1.001,
"price":1.11
}
#精确查询price为1.11的数据
GET myindex-2_09/_search
{
"query": {
"term": {
"price": {
"value": "1.11"
}
}
}
}
#一个酒店搜索项目,酒店的索引除了包含酒店名称、城市、价格、星级、评论数之外,还需要定义是否
满房等。
PUT /hotel/_mapping
{
"properties": {
"full_room": {
"type": "boolean"
}
}
}
#插入数据
POST /hotel/_doc/001
{
"title":"文雅酒店",
"city":"上海",
"price":270,
"start":10,
"comment_count":2,
"full_room":true
}
#查询满房的酒店
GET hotel/_search
{
"query": {
"term": {
"full_room": {
"value": "true"
}
}
}
}
#返回结果如下
{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 0.2876821,
"hits" : [
{
"_index" : "hotel",
"_type" : "_doc",
"_id" : "001",
"_score" : 0.2876821,
"_source" : {
"title" : "文雅酒店",
"city" : "上海",
"price" : 270,
"start" : 10,
"comment_count" : 2,
"full_room" : true
}
}
]
}
}
1.创建索引myindex-2_03映射并指定is_published字段类型为布尔类型
#创建索引映射并指定is_published字段类型为布尔类型
PUT myindex-2_03
{
"mappings": {
"properties": {
"is_published": {
"type": "boolean"
}
}
}
}
#新增数据,字段值必须和映射类型匹配
POST myindex-2_03/_doc/1?pretty
{
"is_published": "true"
}
POST myindex-2_03/_doc/2?pretty
{
"is_published": true
}
#查询索引库中is_publish字段的值是true的数据
GET myindex-2_03/_search
{
"query": {
"term": {
"is_published": {
"value": "true"
}
}
}
}
#返回结果如下
{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 0.6931471,
"hits" : [
{
"_index" : "myindex-2_03",
"_type" : "_doc",
"_id" : "1",
"_score" : 0.6931471,
"_source" : {
"is_published" : "true"
}
}
]
}
}
#在使用布尔类型字段时需要注意的是,布尔类型的查询不能使用0或者1代替,否则会抛出异常
POST myindex-2_03/_doc/3?pretty
{
"is_published": 1
}
#返回结果如下
{
"error" : {
"root_cause" : [
{
"type" : "mapper_parsing_exception",
"reason" : "failed to parse field [is_published] of type [boolean] in
document with id '3'. Preview of field's value: '1'"
}
],
"type" : "mapper_parsing_exception",
"reason" : "failed to parse field [is_published] of type [boolean] in document
with id '3'. Preview of field's value: '1'",
"caused_by" : {
"type" : "json_parse_exception",
"reason" : "Current token (VALUE_NUMBER_INT) not of boolean type\n at [Source:
(ByteArrayInputStream); line: 2, column: 20]"
}
},
"status" : 400
}
#可以看到,使用1作为筛选值进行查询时不能正确地转换为布尔类型的值。如果需要对布尔值进行转换,可以使用
"运行时"脚本来处理
GET myindex-2_03/_search
{
"fields": [
{
"field": "weight"
}
],
"runtime_mappings": {
"weight": {
"type": "long",
"script": "emit(doc['is_published'].value?1:0)"
}
}
}
#返回结果如下
{
"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" : "myindex-2_03",
"_type" : "_doc",
"_id" : "2",
"_score" : 1.0,
"_source" : {
"is_published" : false
},
"fields" : {
"weight" : [
0
]
}
},
{
"_index" : "myindex-2_03",
"_type" : "_doc",
"_id" : "1",
"_score" : 1.0,
"_source" : {
"is_published" : "true"
},
"fields" : {
"weight" : [
1
]
}
}
]
}
}
#一个酒店搜索项目,酒店的索引除了包含酒店名称、城市、价格、星级、评论数、是否满房之外,还需要定义日期等。
PUT /hotel/_mapping
{
"properties": {
"create_time": {
"type": "date"
}
}
}
#插入数据
POST /hotel/_doc/001
{
"title":"文雅酒店",
"city":"上海",
"price":270,
"start":10,
"comment_count":2,
"full_room":true,
"create_time":"20210115"
}
#搜索创建日期为2015年的酒店
GET hotel/_search
{
"query": {
"range": {
"create_time": {
"gte": "20150101",
"lt": "20220112"
}
}
}
}
#返回结果如下
{
"took" : 14,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "hotel",
"_type" : "_doc",
"_id" : "001",
"_score" : 1.0,
"_source" : {
"title" : "文雅酒店",
"city" : "上海",
"price" : 270,
"start" : 10,
"comment_count" : 2,
"full_room" : true,
"create_time" : "20210115"
}
}
]
}
}
#设置create_time字段的格式为yyyy-MM-dd HH:mm:ss
PUT /hotel
{
"mappings": {
"properties": {
"title": {
"type": "text"
},
"city": {
"type": "keyword"
},
"price": {
"type": "double"
},
"start": {
"type": "byte"
},
"comment_count": {
"type": "integer"
},
"full_room": {
"type": "boolean"
},
"create_time": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss"
}
}
}
}
#插入数据
POST /hotel/_doc/001
{
"title":"文雅酒店",
"city":"上海",
"price":270,
"start":10,
"comment_count":2,
"full_room":true,
"create_time":"20210115"
}
#返回结果如下
{
"error" : {
"root_cause" : [
{
"type" : "mapper_parsing_exception",
"reason" : "failed to parse field [create_time] of type [date] in document
with id '001'. Preview of field's value: '20210115'"
}
],
"type" : "mapper_parsing_exception",
"reason" : "failed to parse field [create_time] of type [date] in document
with id '001'. Preview of field's value: '20210115'",
"caused_by" : {
"type" : "illegal_argument_exception",
"reason" : "failed to parse date field [20210115] with format [yyyy-MM-dd
HH:mm:ss]",
"caused_by" : {
"type" : "date_time_parse_exception",
"reason" : "Text '20210115' could not be parsed at index 0"
}
}
},
"status" : 400
}
#插入create_time的格式为yyyy-MM-dd HH:mm:ss数据
POST /hotel/_doc/001
{
"title":"文雅酒店",
"city":"上海",
"price":270,
"start":10,
"comment_count":2,
"full_room":true,
"create_time":"2021-01-15 01:23:30"
}
#创建索引映射并指定date字段的字段类型为日期类型
PUT myindex-2_04
{
"mappings": {
"properties": {
"date":{
"type": "date"
}
}
}
}
#插入文档数据
PUT myindex-2_04/_doc/1
{
"date":"2015-01-01"
}
#插入文档数据
PUT myindex-2_04/_doc/2
{
"date": "2015-01-01T12:10:30Z"
}
#插入文档数据
PUT myindex-2_04/_doc/3
{
"date":1420070400001
}
#以上3种不同格式的日期数据都被插入到索引库中。
#创建索引并为日期类型的字段指定具体的日期格式
PUT myindex-2_05
{
"mappings": {
"properties": {
"date": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss"
}
}
}
}
#以下语句插入文档数据时将会抛出异常,因为日期内容不符合映射格式
PUT myindex-2_05/_doc/1
{
"date":"2015-01-01"
}
#以下语句插入文档数据时将会抛出异常,因为日期内容不符合映射格式
PUT myindex-2_05/_doc/2
{
"date":"2015-01-01T12:10:30Z"
}
#以下语句插入文档数据时将会抛出异常,因为日期内容不符合映射格式
PUT myindex-2_05/_doc/3
{
"date":1420070400001
}
#以下语句文档数据正常插入,因为日期内容符合字段指定的日期格式
PUT myindex-2_05/_doc/4
{
"date":"2015-01-01 12:02:56"
}
PUT /索引库名称
{
"mappings": {
"properties": {
"location": {
"type": "geo_shape"
}
}
}
}
PUT 索引库名称
{
"mappings": {
"properties": {
"location": {
"type": "geo_point"
}
}
}
}
#一个酒店搜索项目,酒店的索引除了包含酒店名称、城市、价格、星级、评论数、是否满房、日期之外,还需要定义位
置等。
PUT /hotel/_mapping
{
"properties": {
"location": {
"type": "geo_point"
}
}
}
#插入数据
POST /hotel/_doc/001
{
"title":"文雅酒店",
"city":"上海",
"price":270,
"start":10,
"comment_count":2,
"full_room":true,
"create_time":"2021-01-15 01:23:30",
"location":{
"lat":40.012134,
"lon":116.497553
}
}
#搜索指定的两个地理位置形成的矩形范围中包含的酒店信息
GET hotel/_search
{
"query": {
"bool": {
"must": [
{
"match_all": {}
}
],
"filter": {
"geo_bounding_box": {
"location": {
"top_left": {
"lat": 40.73,
"lon": -74.1
},
"bottom_right": {
"lat": 40.01,
"lon": -71.12
}
}
}
}
}
}
}
#搜索指定的多个地理位置形成的多边形范围中包含酒店信息
GET /hotel/_search
{
"query": {
"bool": {
"must": [
{
"match_all": {}
}
],
"filter": {
"geo_polygon": {
"location": {
"points": [
{
"lat": 40.73,
"lon": -74.1
},
{
"lat": 40.83,
"lon": -75.1
},
{
"lat": 40.93,
"lon": -76.1
}
]
}
}
}
}
}
}
#搜索指定位置1000km范围内的酒店数据
GET /hotel/_search
{
"query": {
"bool": {
"must": [
{
"match_all": {}
}
],
"filter":{
"geo_distance": {
"distance": "1000km",
"location": {
"lat": 40.73,
"lon": -74.1
}
}
}
}
}
}
#搜索距离指定位置一定范围内有多少个酒店
GET /hotel/_search
{
"size": 0,
"aggs": {
"count_by_distinct": {
"geo_distance": {
"field": "location",
"origin": {
"lat": 52.376,
"lon": 4.894
},
"ranges": [
{
"from": 100,
"to": 300
}
],
"unit": "mi",
"distance_type": "arc"
}
}
}
}
#创建索引映射并指定location字段的字段类型为geo_shape类型
PUT myindex-geo_shape
{
"mappings": {
"properties": {
"location": {
"type": "geo_shape"
}
}
}
}
#插入地点相关信息
POST /myindex-geo_shape/_doc?refresh
{
"name": "Wind & Wetter,Berlin,Germany",
"location": {
"type": "point",
"coordinates": [
13.400544,
52.530286
]
}
}
#搜索指定的两个位置范围内的地点
GET /myindex-geo_shape/_search
{
"query": {
"bool": {
"must": [
{
"match_all": {}
}
],
"filter": {
"geo_shape": {
"location": {
"shape": {
"type": "envelope",
"coordinates": [
[
13,
53
],
[
14,
52
]
]
},
"relation": "within"
}
}
}
}
}
}
#返回的结果
{
"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" : "myindex-geo_shape",
"_type" : "_doc",
"_id" : "oKSWWYcB7w4YX5_iGU4l",
"_score" : 1.0,
"_source" : {
"name" : "Wind & Wetter,Berlin,Germany",
"location" : {
"type" : "point",
"coordinates" : [
13.400544,
52.530286
]
}
}
}
]
}
}
#向hotel中添加一条数据
PUT /hotel/_doc/002
{
"title": "好再来酒店",
"city": "青岛",
"price": 578.23,
"comment_info": {
"properties": {
"favourable_comment": 199,
"negative_comment": 68
}
}
}
#执行以上DSL后,索引hotel增加了一个字段comment_info,它有两个属性,分别是favourable_comment
和negative_comment,二者的类型都是long。
#查看hotel的mapping
GET /hotel/_mapping
#hotel 的mapping 响应结果为:
{
"hotel" : {
"mappings" : {
"properties" : {
"city" : {
"type" : "keyword"
},
"comment_count" : {
"type" : "integer"
},
"comment_info" : {
"properties" : {
"properties" : {
"properties" : {
"favourable_comment" : {
"type" : "long"
},
"negative_comment" : {
"type" : "long"
}
}
}
}
},
"create_time" : {
"type" : "date",
"format" : "yyyy-MM-dd HH:mm:ss"
},
"full_room" : {
"type" : "boolean"
},
"location" : {
"type" : "geo_point"
},
"price" : {
"type" : "double"
},
"start" : {
"type" : "byte"
},
"title" : {
"type" : "text"
}
}
}
}
}
#根据对象类型的属性进行搜索,可以直接用"."操作符进行指向。
#例如搜索hotel索引中好评数大于200的文档
GET /hotel/_search
{
"query": {
"range": {
"comment_info.properties.favourable_comment": {
"gte": 36
}
}
}
}
#当然,对象内部还可以包含对象
#评论信息字段comment_info可以增加前3条好评数据
POST /hotel/_doc/002
{
"title": "好再来酒店",
"city": "青岛",
"price": 578.23,
"comment_info": {
"properties": {
"favourable_comment": 199,
"negative_comment": 68,
"top3_favourable_comment": {
"top1": {
"content": "干净整洁的一家酒店",
"score":87
},
"top2": {
"content": "服务周到,停车方便",
"score":89
},
"top3": {
"content": "闹中取静,环境优美",
"score":90
}
}
}
}
}
#创建索引映射
PUT myindex-object
{
"mappings": {
"properties": {
"region": {
"type": "keyword"
},
"manager": {
"properties": {
"age": {
"type": "integer"
},
"name": {
"properties": {
"first": {
"type": "text"
},
"last": {
"type": "text"
}
}
}
}
}
}
}
}
#对于_id等于1的文档而言,manager是一个对象,该对象中又包含一个name对象,而name对象中有两个键值对。如果需
要向这个索引映射中插入文档,可以使用下面任何一种方式写入
#范例一:使用嵌套的JSON数据格式进行写入
#使用嵌套的JSON数据格式进行写入
PUT myindex-object/_doc/1
{
"region":"China",
"manager":{
"age":30,
"name":{
"first":"clay",
"last":"zhagng"
}
}
}
#范例二:使用简单的JSON数据格式进行写入
#使用简单的JSON数据格式进行写入
PUT myindex-object/_doc/2
{
"region": "US",
"manager.age": 30,
"manager.name.first": "John",
"manager.name.last": "Smith"
}
#使用以上两种方式写入数据不会影响数据的存储,但是会影响查询返回的结果。
#查询数据
GET myindex-object/_doc/_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" : "myindex-object",
"_type" : "_doc",
"_id" : "1",
"_score" : 1.0,
"_source" : {
"region" : "China",
"manager" : {
"age" : 30,
"name" : {
"first" : "clay",
"last" : "zhagng"
}
}
}
},
{
"_index" : "myindex-object",
"_type" : "_doc",
"_id" : "2",
"_score" : 1.0,
"_source" : {
"region" : "US",
"manager.age" : 30,
"manager.name.first" : "John",
"manager.name.last" : "Smith"
}
}
]
}
}
#以上返回信息的写入格式与查询返回的格式一致。
#为hotel索引增加一个标签字段,名称为tag
PUT /hotel/_mapping
{
"properties": {
"tag": {
"type": "keyword"
}
}
}
#查看一下索引hotel的mapping
GET /hotel/_mapping
#返回的结果如下
{
"hotel" : {
"mappings" : {
"properties" : {
"city" : {
"type" : "keyword"
},
"comment_count" : {
"type" : "integer"
},
"comment_info" : {
"properties" : {
"properties" : {
"properties" : {
"favourable_comment" : {
"type" : "long"
},
"negative_comment" : {
"type" : "long"
},
"top3_favourable_comment" : {
"properties" : {
"top1" : {
"properties" : {
"content" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"score" : {
"type" : "long"
}
}
},
"top2" : {
"properties" : {
"content" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"score" : {
"type" : "long"
}
}
},
"top3" : {
"properties" : {
"content" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"score" : {
"type" : "long"
}
}
}
}
}
}
}
}
},
"create_time" : {
"type" : "date",
"format" : "yyyy-MM-dd HH:mm:ss"
},
"full_room" : {
"type" : "boolean"
},
"location" : {
"type" : "geo_point"
},
"price" : {
"type" : "double"
},
"start" : {
"type" : "byte"
},
"tag" : {
"type" : "keyword"
},
"title" : {
"type" : "text"
}
}
}
}
}
#通过返回的mapping信息来看,新增的tag字段与普通的keyword类型字段没什么区别,现在写入一条数据
PUT /hotel/_doc/004
{
"title":"好再来酒店",
"city":"青岛",
"price":"578.23",
"tags":["有车位","免费WIFI"]
}
#查询一下写入的数据
GET /hotel/_search
#返回的数据为
{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 3,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "hotel",
"_type" : "_doc",
"_id" : "001",
"_score" : 1.0,
"_source" : {
"title" : "文雅酒店",
"city" : "上海",
"price" : 270,
"start" : 10,
"comment_count" : 2,
"full_room" : true,
"create_time" : "2021-01-15 01:23:30",
"location" : {
"lat" : 40.012134,
"lon" : 116.497553
}
}
},
{
"_index" : "hotel",
"_type" : "_doc",
"_id" : "002",
"_score" : 1.0,
"_source" : {
"title" : "好再来酒店",
"city" : "青岛",
"price" : 578.23,
"comment_info" : {
"properties" : {
"favourable_comment" : 199,
"negative_comment" : 68,
"top3_favourable_comment" : {
"top1" : {
"content" : "干净整洁的一家酒店",
"score" : 87
},
"top2" : {
"content" : "服务周到,停车方便",
"score" : 89
},
"top3" : {
"content" : "闹中取静,环境优美",
"score" : 90
}
}
}
}
}
},
{
"_index" : "hotel",
"_type" : "_doc",
"_id" : "004",
"_score" : 1.0,
"_source" : {
"title" : "好再来酒店",
"city" : "青岛",
"price" : "578.23",
"tags" : [
"有车位",
"免费WIFI"
]
}
}
]
}
}
#通过以上信息可以看到,写入的数据的tag字段已经是数组类型了。那么,数组类型的数据如何搜索呢?
#数组类型的字段适用于元素类型的搜索方式,也就是说,数组元素适用于什么搜索,数组字段就适用于什么搜索。
#在上面的示例中,数组元素类型是keyword,该类型可以适用于term搜索,则tag字段也可以适用于term搜索
GET /hotel/_search
{
"query": {
"term": {
"tags": {
"value": "有车位"
}
}
}
}
#ES中的空数组可以作为missing field,即没有值的字段,下面的DSL将插入一条tag为空的数组
POST /hotel/_doc/003
{
"title":"环球酒店",
"city":"青岛",
"price":"530.00",
"tags":[]
}
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。