elasticsearch之mapping types

document中每一个field的数据类型可以通过types来设置。

1:主类型

每一个json field都可以对应到一个特定的主类型,json本身就提供了很多类型。

string/byte/short/integer/long/float/double/boolean/binary/date/null。

以上数据类型跟通常的数据类型一样,没什么特殊性。下边介绍一些特有的:

token_count:这种类型索引和存储的是json串中的token数目,而非json串本身。因此需要携带一个analyzer。为了达到最佳性能,采用no token filter的analyzer。

注意:token_count不会忽略stop words。

fielddata filters:这不是一种数据类型,只是一个配置项。可以控制field的哪些value可以加载到内存中,在对string field进行facet时尤其有用。fielddata filter可以排除不满足条件的terms,比如无法匹配到指定的正则,tf不在指定范围内等。下边是一个例子:

{
    tweet: {
        type:      "string",
        analyzer:  "whitespace"
        fielddata: {
            filter: {
                regex: {
                    "pattern":        "^#.*"
                },
                frequency: {
                    min:              0.001,
                    max:              0.1,
                    min_segment_size: 500
                }
            }
        }
    }
}
similarity:es允许给field配置一个相似性算法,默认的TF/IDF。

copy to field:copy_to参数将指定该field中的所有value都将拷贝到参数指定的field中。比如:

{
  "book" : {
    "properties" : {
      "title" : { "type" : "string", "copy_to" : "meta_data" },
      "abstract" : { "type" : "string", "copy_to" : "meta_data" },
      "meta_data" : { "type" : "string" }
    }
}
同样支持多个field,比如:

{
  "book" : {
    "properties" : {
      "title" : { "type" : "string", "copy_to" : ["meta_data", "article_info"] }
    }
}
multi field:同一个json串指定不同的处理方式。比如:

{
  "tweet" : {
    "properties" : {
      "name" : {
        "type" : "string",
        "index" : "analyzed",
        "fields" : {
          "raw" : {"type" : "string", "index" : "not_analyzed"}
        }
      }
    }
  }
}

name字段被处理的两次,一次采用默认的analyzer,另一次完全跳过analysis过程。因此衍生出一种访问方式:name.raw.

field的include_in_all属性决定该field是否应该被包含到_all字段中。在multi_field的情况下,该设置只对主字段有效,在fields中的设置会忽略。

在本质上field是无法更新的。但是muti fields可以添加到已经存在的field中。这就允许在主字段已经存在一个分词器的情况下,再添加另外一个分词器。当然新添加的muti field设置也只是对添加之后再进入索引的文档有效,之前的文档当然是无效的。Another important note is that new multi fields will be merged into the list of existing multi fields, so when adding new multi fields for a field previous added multi fields don’t need to be specified.

2:array type

json可以支持数组,数组内容可以是主类型,当然也可以是对象类型。对array类型不能被简单的mapping,因为array类型是自动检测的,并且要用core type或者object type来映射。如下:

{
    "tweet" : {
        "message" : "some arrays in this tweet...",
        "tags" : ["elasticsearch", "wow"],
        "lists" : [
            {
                "name" : "prog_list",
                "description" : "programming list"
            },
            {
                "name" : "cool_list",
                "description" : "cool stuff list"
            }
        ]
    }
}

以上tags是一个string数组,而lists是一个对象数组。

下边是以上document的一个显式的mapping设置:

{
    "tweet" : {
        "properties" : {
            "message" : {"type" : "string"},
            "tags" : {"type" : "string", "index_name" : "tag"},
            "lists" : {
                "properties" : {
                    "name" : {"type" : "string"},
                    "description" : {"type" : "string"}
                }
            }
        }
    }
}

注意:tags的index_name属性。

事实上,array类型是可以被自动支持的。以下document也是ok的:

{
    "tweet" : {
        "message" : "some arrays in this tweet...",
        "tags" : "elasticsearch",
        "lists" : {
            "name" : "prog_list",
            "description" : "programming list"
        }
    }
}

注意:我们可以用index_name来访问array中的单数形式数据(以上例子中用tag来代替tags),事实上我们可以直接用index_name来直接访问。

比如:我们可以用tweet.tags来访问该字段,也可以用用tweet.tag来访问.

其实index_name只是为了array的单数形式设置的,在导入数据的时候如果发现是单数形式,可以直接用index_name这个属性(这时候source字段是不带方括号,当然如果是单数形式也用了tags字段,source也是不带方括号的)。而在查询的时候,既可以用tags,也可以用tag。

3:object type

json是结构化的数据,可以嵌套。es对这种结构化数据进行了合理的映射,而且是动态的。

{
    "tweet" : {
        "person" : {
            "name" : {
                "first_name" : "Shay",
                "last_name" : "Banon"
            },
            "sid" : "12345"
        },
        "message" : "This is a tweet!"
    }
}
person就是一个object,同时tweet也是object,尽管是一个特殊的root object type。下边是一个显式的object mapping

{
    "tweet" : {
        "properties" : {
            "person" : {
                "type" : "object",
                "properties" : {
                    "name" : {
                        "type" : "object",
                        "properties" : {
                            "first_name" : {"type" : "string"},
                            "last_name" : {"type" : "string"}
                        }
                    },
                    "sid" : {"type" : "string", "index" : "not_analyzed"}
                }
            },
            "message" : {"type" : "string"}
        }
    }
}
name的type设置为object。其实这要设置了properties属性,会自动定义为object类型。

properties定了了object的各个field,其中的field仍然可以定义为object或者是core-type

es一个重要特性就是动态mapping,以上例子中如果在person的document中出现了新的field,比如age,则会自动添加到mapping中。可以关闭dynamic属性,这样就会拒绝不在mapping中的数据。dynamic没有任何额外的负载,关闭只是为了防止不符合格式的数据进入。dynamic在第一条数据进入的时候会自动推测数据类型,添加到mapping中,比如如果是一个number,则会自动映射到number的core type,其他属性采用默认值。日期类型有些特殊,因为是用string表示,在进入es的时候,parse之后可以认为是一个日期类型,可以配置dynamic_date_formats来设置日期的格式。

注意:一旦一个field的类型被确定了,就无法更改。

enabled标志可以让object的parse和index失效,也就是说在这个对象将不会被索引。当json doc中有部分包含随意的json信息而不应该被索引的时候,设置mapping中的enable属性即可。

{
    "tweet" : {
        "properties" : {
            "person" : {
                "type" : "object",
                "properties" : {
                    "name" : {
                        "type" : "object",
                        "enabled" : false
                    },
                    "sid" : {"type" : "string", "index" : "not_analyzed"}
                }
            },
            "message" : {"type" : "string"}
        }
    }
}
以上,name及其内容将不会被索引。

include_in_all可以设置在object type的级别上,会自动延伸到内部的mapping中。

4:root object type

root object mapping是对type本身的映射。对object type适用的mapping对root object 也适用。root object typemapping允许索引不指定type的document。比如:

{

“message” : “This is a tweet”

}

可以指定type级别的过滤器类型:

{
    "tweet" : {
        "index_analyzer" : "standard",
        "search_analyzer" : "standard"
    }
}

在任何没有显式指定的field中的过滤器自动应用以上设置。

可以设置动态date类型的格式:

{
    "tweet" : {
        "dynamic_date_formats" : ["yyyy-MM-dd", "dd-MM-yyyy"],
        "properties" : {
            "message" : {"type" : "string"}
        }
    }
}

如果检测到一个string是date,则标记为date类型,采用以上设置的格式。

注意:以上设置只能针对动态date,不适用于在mapping中显式指定的date类型。

可以设置是否允许date的自动检测:

{
    "tweet" : {
        "date_detection" : false,
        "properties" : {
            "message" : {"type" : "string"}
        }
    }
}

可以设置number类型的自动检测(有时候number类型是用string传递过来的):

{
    "tweet" : {
        "numeric_detection" : true,
        "properties" : {
            "message" : {"type" : "string"}
        }
    }
}

可以设置动态模板(注意,只对确实有value的field有效,如果是null,则并不会应用),如下:

{
    "person" : {
        "dynamic_templates" : [
            {
                "template_1" : {
                    "match" : "multi*",
                    "mapping" : {
                        "type" : "{dynamic_type}",
                        "index" : "analyzed",
                        "fields" : {
                            "org" : {"type": "{dynamic_type}", "index" : "not_analyzed"}
                        }
                    }
                }
            },
            {
                "template_2" : {
                    "match" : "*",
                    "match_mapping_type" : "string",
                    "mapping" : {
                        "type" : "string",
                        "index" : "not_analyzed"
                    }
                }
            }
        ]
    }
}

以上对所有以muti开头的field都设置成了multifield类型(template1),所有string类型的field都应用not_analyzed选项。

mapping中的具体属性不再具体介绍:比如{dynamic_type}这个变量是指动态detect出来的类型,比如date等。

完全通用的设置也可以应用:

{
    "person" : {
        "dynamic_templates" : [
            {
                "store_generic" : {
                    "match" : "*",
                    "mapping" : {
                        "store" : true
                    }
                }
            }
        ]
    }
}

以上说明,所有的字段都stored。

注意,一般以上的通用设置要放在template list最后,因为如果多个mapping匹配到同一个field,则只有第一个会被应用,也就是越往前的优先级越高。

5:nested object type

nested object type跟object type类似,不同点在于:一个object 组成的array 是扁平的,而一个nested object组成的array每一个object是独立的。比如:

{
    "group" : "fans",
    "user" : [
        {
            "first" : "John",
            "last" :  "Smith"
        },
        {
            "first" : "Alice",
            "last" :  "White"
        },
    ]
}

以上document中,user如果是一个object type,则存储是这样的:

{
    "group" :        "fans",
    "user.first" : [ "alice", "john" ],
    "user.last" :  [ "smith", "white" ]
}

丧失了first 跟 last的关系。

而如果user是一个nested object type,则存储是这样的:


    "user.first" : "alice",
    "user.last" :  "white"
}

    "user.first" : "john",
    "user.last" :  "smith"
}

    "group" :       "fans"
}

显然每一个object作为单独的一个document存储了,维持了object中field之间的关系。

因此,如果查询alice AND smith是不会有匹配结果的。

对nested object的查询可以使用nested query或者nested filter。

nested object的显式mapping如下定义:

{
    "type1" : {
        "properties" : {
            "users" : {
                "type" : "nested",
                "properties": {
                    "first" : {"type": "string" },
                    "last"  : {"type": "string" }
                }
            }
        }
    }
}

也许,我们想要我们的object既要是nested object,也要flat object,则可以如下设置:

{
    "type1" : {
        "properties" : {
            "users" : {
                "type" : "nested",
                "include_in_parent": true,
                "properties": {
                    "first" : {"type": "string" },
                    "last"  : {"type": "string" }
                }
            }
        }
    }
}

使用include_in_parent选项。实际存储如下:


    "user.first" : "alice",
    "user.last" :  "white"
}

    "user.first" : "john",
    "user.last" :  "smith"
}

    "group" :        "fans",
    "user.first" : [ "alice", "john" ],
    "user.last" :  [ "smith", "white" ]
}

nested object可能还会包含nested object,include_in_parent只会设置到其直接parent上,如果设置到最顶层root parent上,则需要使用include_in_root选项。

在内部,nested object是作为额外的文档被索引的,但是,因为可以确保存储在同一个block上,因此,在与parent docs进行join时速度也非常快。

在针对index执行操作时(比如执行一个match_all类型的查询)这种内部的nested document会被自动隐藏,但是在执行nested query的时候,这种关联关系就显现出来了。

因为nested object对parent doc总是被掩藏的,因此nested docs不能在nested query范围之外被访问。例如:在nested object内部field的store属性可以enable,但是却不能检索它们,因此,stored field是在nested query范围之外fetch的。

_source field也是跟parent document相关联的,因此可以通过source获取到nested object的field 值并返回。

6:ip type

存储ipv4地址的类型。

7:geo point type and geo shape type

存储地理位置的类型。

point支持维度在前,精度在后格式。可以为数组,字符串等。

shape定义了矩形,多边形,三角形等。

其中请注意精度设置。

8:attachment type

定义了附件的类型,比如doc,pdf等,内容是用base64编码的。需要插件的支持,底层使用的是apache的tika。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值