elasticsearch中的数据类型:flattened和join

打印 上一主题 下一主题

主题 866|帖子 866|积分 2598

flattened:比如你有一个字段的值是一个json,这个json里面又有很多字段,你又不想一个一个的定义这些字段到mapping,就可以用flattened
直接动手:创建索引:
  1. PUT person
  2. {
  3.   "mappings": {
  4.     "properties": {
  5.       "patient_name": {
  6.         "type": "text"
  7.       },
  8.       "detail": {
  9.         "type": "flattened"
  10.       }
  11.     }
  12.   }
  13. }
复制代码
注意这里detail字段类型为flattened, 然后插入文档:
  1. PUT person/_doc/1
  2. {
  3.   "patient_name": "John Doe",
  4.   "detail": {
  5.     "age": 143,
  6.     "skills": [
  7.       "java",
  8.       "python",
  9.       "ai"
  10.     ],
  11.     "history": "none",
  12.     "friends": [
  13.       "Neo",
  14.       "James",
  15.       "Tony Stark"
  16.     ]
  17.   }
  18. }
复制代码
然后搜索:
  1. GET person/_search
  2. {
  3.   "query": {
  4.     "match": {
  5.       "detail": "java"
  6.     }
  7.   }
  8. }
复制代码
注意这里直接搜索detail,可以搜索到我们刚刚插入的那个文档,但是我们也可以搜索detail.skills,比如
  1. "detail.skills": "java"
复制代码
也能搜索到那个文档,但是如果我们这样搜索就搜索不到:
  1. "detail.friends": "java"
复制代码
还有一点,这里的每个字段会被定义成keyword类型,所以你如果这样搜索就搜索不到:
  1. "detail.friends": "Tony"
复制代码
你必须完全匹配才能搜索的到:
  1. "detail.friends": "Tony Stark"
复制代码
 
再来看看join类型,说的是一个索引里面一个文档和其他几个文档有关联,比如几个文档的父文档都是那一个文档,动手:
先创建索引:
  1. PUT person2
  2. {
  3.   "mappings": {
  4.     "properties": {
  5.       "relationship": {
  6.         "type": "join",
  7.         "relations": {
  8.           "star": "fans"
  9.         }
  10.       }
  11.     }
  12.   }
  13. }
复制代码
这里relationship是一个字段名,类型是join,指的明星和粉丝的关系,所以里面有一个类型的参数relations,它的取值star:fans分别表示父和子的关联类型,后面会用到。
插入文档,首先是父文档:
  1. PUT person2/_doc/1
  2. {
  3.   "name": "star1",
  4.   "relationship": {
  5.     "name": "star"
  6.   }
  7. }
复制代码
这里的relationship.name是star,这个值是在前面mapping里面定义的,前面提到过,如果你写个super_star,就会报错:
unknown join name [super_star] for field [relationship]
 
然后插入第一个子文档:
  1. PUT person2/_doc/2?routing=tony
  2. {
  3. "name":"fan1",
  4. "relationship":{
  5. "name":"fans",
  6. "parent":1
  7. }
  8. }
复制代码
注意这里有个routing参数,如果插入子文档的时候没有指定routing是会报错的,这是为了将相关的文档分配到相同的分片,比如后面插入第二个子文档真爱粉的时候也指定相同的路由参数值。
[routing] is missing for join field [relationship]
还有这里的relationship.name是fans,也是在前面mapping里面定义的。
指定parent是1,就确定了父子文档的关系。
最后插入第二个子文档:
  1. PUT person2/_doc/3?routing=tony
  2. {
  3. "name":"fan2",
  4. "relationship":{
  5. "name":"fans",
  6. "parent":1
  7. }
  8. }
复制代码
路由参数一样,下面查询:
  1. GET person2/_search
  2. {
  3.   "query": {
  4.     "parent_id": {
  5.       "type": "fans",
  6.       "id": 1
  7.     }
  8.   }
  9. }
复制代码
可以查到两个子文档,两个子文档,但是不包括父文档:
  1.     "hits" : [
  2.       {
  3.         ..."_routing" : "tony",
  4.         "_source" : {
  5.           "name" : "fan1",
  6.           "relationship" : {
  7.             "name" : "fans",
  8.             "parent" : 1
  9.           }
  10.         }
  11.       },
  12.       {
  13.         ..."_routing" : "tony",
  14.         "_source" : {
  15.           "name" : "fan2",
  16.           "relationship" : {
  17.             "name" : "fans",
  18.             "parent" : 1
  19.           }
  20.         }
  21.       }
复制代码
如果插入第二个子文档的时候指定路由参数是neo,也可以搜索到两个子文档,不影响搜索,但不建议这样做。
  1. PUT person2/_doc/3?routing=neo<br><br>还有要注意的是如果查询的时候,指定parent_id.type为star会报错:<br>
复制代码
  1. GET person2/_search
  2. {
  3.   "query": {
  4.     "parent_id": {
  5.       "type": "star",
  6.       "id": 1
  7.     }
  8.   }
  9. }
复制代码
报错如下:
[parent_id] no relation found for child [star]
也就是说这里要指定的是子文档的关联类型
  1.  
复制代码
 
  
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

灌篮少年

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表