身安不如心安,屋宽不如心宽 。

keyword居然可以存字符串的同时也能数组

Elasticsearch | 作者 stephen_qu | 发布于2020年05月15日 | 阅读数:7959

原先一直觉得keyword是string的一种特殊形式,默认只能存string。今天在解决一个问题的时候,意外的发现keyword里面可以存数组。
{
"bes_contract_shop_index": {
"mappings": {
"doc": {
"properties": {
"test3": {
"type": "keyword"
}
}
}
}
}
}

{71CE74AF-FEAB-4646-8398-92396E9A3F63}_20200515153722.jpg

 
那么引出几个问题:
1. ES是怎么存储这个数组的
2. ES中array 这个类型,数组一般用什么类型存储
3.查询的时候,通过数组中的某一个值,怎么能够命中这个doc
已邀请:

Ombres

赞同来自:

索引中存的是 term ,也就是分词的 后的结果,某个字段的值就可能分成多个term 
某个字段数据倒排索引类似于
term          postinglist
中国           1,2,3
美国           2,3
 
理解了以上结构,那么我觉得对于多值并不难理解,一段话本质上就是多个term,也就是一个 数组 
 
简单回答
1.  es存储多值,其实就是把keyword当成一个term来处理的,只要在对应的posting list上加入doc的id就可以了
2.  取决于定义的字段类型,keyword 就是string
3.  查询的时候,通过倒排索引中某个term就能获取到doc的id
 

yanyyy

赞同来自:

这个问题,大佬们就没人回答呐

Charele - Cisco4321

赞同来自:

Ombres的说法是没错的,不过只说了分词后是怎么进倒排表的,
但这好像不是这个问题的答案。 
实际上不光是keyword类型,任何ES中的类型都可以存成“数组”形式的。
比如name: keyword,你用PUT "aaa"就是单个值,用PUT ["xxx", "yyy"]就是“数组”
比如age: long,你用PUT 123就是单个值,用PUT [1111, 2222]就是“数组”类型
 
这个“数组”,加双引号,是因它是一个抽像的概念,
其实ES中并没有"array"这样一个类型  (有vector这个类型,那是另外的话题)
 
这只是一个文档里一个变量有多个值,
就像一个人的姓名,有的人只有一个名字,有的人有两个名字。
 
至于这是如何实现,如果了解Lucene,很容易理解这个问题。
(伪代码:)
Document doc1 = ...
doc1.addField("name", "aaa")

Document doc2 = ...
doc2.addField("name", "xxx")
doc2.addField("name", "yyy") 
 
 
 
 
 
 
 
 

要回复问题请先登录注册