什么是nested类型
在理解nested类型之前, 我们还需要理解object类型, 所以你需要看查看以下两个官方文档:
- Object datatype
- Nested datatype
简单的说, Elasticsearch中的文档支持存储嵌套的json结构, 如
{
"group" : "fans",
"user" : [
{
"first" : "John",
"last" : "Smith"
},
{
"first" : "Alice",
"last" : "White"
}
]
}
如果我们将以上json插入到文档中, user字段会被dynamic mapping为object类型
现在 user下的first字段也能被索引到, 但object类型有一个特性是会将数据拍扁为以下结构:
{
"group" : "fans",
"user.first" : [ "alice", "john" ],
"user.last" : [ "smith", "white" ]
}
可以看到, first和last(也就是alice和white)没有了关联关系, 在query的时候就会返回错误结果.
现在就需要nested上场了, 如果user是nested类型, 那么数据将会被独立为多个独立文档以保障嵌套字段间的关系.
{
"user.first" : "alice",
"user.last" : "white"
}
{
"user.first" : "john",
"user.last" : "smith"
}
使用nested
上面也说到, 如果使用默认的dynamic mapping, json对象会被匹配为object类型, 如果要使用nested你就需要再创建Index的时候指定mapping
- indices-create
- mapping
值得注意的是在查询嵌套结构的时候也和普通的query不同, 需要使用到nested-query
例如一个文档的mapping是这样的:
{
"mappings": {
"type1" : {
"properties" : {
"obj1" : {
"type" : "nested"
}
}
}
}
}
就需要这样写query语句
{
"query": {
"nested" : {
"path" : "obj1",
"query" : {
"bool" : {
"must" : [
{ "match" : {"obj1.name" : "blue"} },
{ "range" : {"obj1.count" : {"gt" : 5}} }
]
}
}
}
}
}
Dynamic templates
当动态添加字段的时候Elasticsearch会自动推断类型, 如string就会使用text
类型存储.
但如果你需要修改这个逻辑就需要使用到dynamic templates.
比如在上面的例子中, 我们需要对动态添加的user.first字段进行精确搜索, 而不是全文搜索, 就需要使用到keyword类型. 为了达到这个目的, 我们可以这样写dynamic_templates
PUT my_index
{
"mappings": {
"my_type": {
"dynamic_templates": [
{
"strings_as_keywords": {
"match_mapping_type": "string",
"mapping": {
"type": "keyword"
}
}
}
]
}
}
}
当然这个用法只是dynamic_template的冰山一角, 更多用法请参考官方文档 - Dynamic templates
text 与 keyword 类型
text datatype是我们最常用的类型, 可以用来实现全文搜索, 原理是在入库的时候text类型的字段会被analyzer(分析器)分割成多个terms再被索引, 这也是实现Inverted index(倒排索引)步骤之一.
keyword datatype和text不同的时候, keyword不会被分析, 所有的内容都将被存储为一个term. 它通常被用于 过滤, 排序, 聚合, 而不是搜索.
你可以在文档 - term-qury中找到Why doesn’t the term query match my document?段来理解什么是analyzer, keyword, text.