映射
Elasticsearch中的mapping(映射)对应数据库中的表结构
GET /gb/_mapping/tweet
返回:
Elasticsearch核心简单字段类型:
类型 | 表示的数据类型 |
String | string |
Whole number | byte, short, integer, long |
Floating point | float, double |
Boolean | boolean |
Date | date |
当你索引一个包含新字段的文档——一个之前没有的字段——Elasticsearch将使用动态映射猜测字段类型,这类型来自于JSON的基本数据类型,使用以下规则:
JSON type | Field type |
Boolean: true or false | boolean |
Whole number: 123 | long |
Floating point: 123.45 | double |
String, valid date: "2014-09-15" | date |
String: "foo bar" | string |
注意
这意味着,如果你索引一个带引号的数字——"123",它将被映射为"string"类型,而不是"long"类型。然而,如果字段已经被映射为"long"类型,Elasticsearch将尝试转换字符串为long,并在转换失败时会抛出异常。
使用技巧
我们可以先同步一条数据让ES自动生成映射,然后复制出来修改部分字段后手动创建映射
定义字段映射规则
前面说到,在同步一个新的字段时,ES会自动生成映射,但有时候默认的映射并不能满足我们的需求,幸运的是我们可以通过设置来自定义这些规则。
比如你不希望把"2014-09-15"的字段映射成date类型,可以使用:
"mappings": {
"my_type": {
"date_detection": false
}}
你也可以修改日期格式的映射规则,如:
"mappings": {
"_default_": {
"_all": {"enabled": false},
"dynamic_date_formats": ["yyyy-MM-dd HH:mm:ss"]
}
}此时只有当字符串格式为"yyyy-MM-dd HH:mm:ss"才会被自动识别为日期类型,并且format就是被识别的格式.
使用 dynamic_templates,你可以完全控制新字段的映射,你设置可以通过字段名或数据类型应用一个完全不同的映射。
PUT /my_index
{
"mappings": {
"my_type": {
"dynamic_templates": [
{ "en": {
"match": "*_en",
"match_mapping_type": "string",
"mapping": {
"type": "string",
"analyzer": "english"
}
}},
{ "not_analyzed": {
"match": "*",
"match_mapping_type": "string",
"mapping": {
"type": "string",
"index": "not_analyzed"
}
}}
]
} }
}
上面的dynamic_templates实现了将以"_en"结尾且类型为string的字段映射为使用“english”分析器的类型,其余的映射为不索引字段
倒排索引
在了解分析的概念前,先要简单了解一下什么是倒排索引
倒排索引(inverted index)的结构是ES用来做快速的全文搜索的。倒排索引由在文档中出现的唯一的单词列表,以及对于每个单词在文档中的位置组成。
例如,我们有两个文档,每个文档content字段包含:
- dog cat bird
- dog girl boy
把它放到倒排索引中的结果如下:
term | Doc_1 | Doc_2 |
dog | X | X |
cat | X | |
bird | X | |
girl | | X |
boy | | X |
当需要查找dog bird时,只需要在索引中查找,如下:
term | Doc_1 | Doc_2 |
dog | X | X |
bird | X | |
total | 2 | 1 |
两个文档都匹配,但是第一个比第二个有更多的匹配项。以此就可以轻易的看到Doc_1的匹配度高于Doc_2的匹配度
当然实际应用中要复杂的多,比如索引中还会保存字符出现的次数和出现的位置,一个长度长的词还会比一个短的词在匹配度计算时占更高的分值等。
实际应用场景中我们还会遇到一些问题:
- 大小写不敏感
- 近义词、复数
- 中文如何进行分词
下面会继续讲解对这些情况处理
分析
分析(analysis)是这样一个过程:
- 首先,标记化一个文本块为适用于倒排索引单独的词(term)
- 然后标准化这些词为标准形式,提高它们的“可搜索性”或“查全率”
分析的过程如下图:
- 字符过滤器(character filter)
首先字符串经过字符过滤器,它们的工作是在标记化前处理字符串。字符过滤器能够去除HTML标记,或者转换"&"为"and"。
- 分词器(tokenizer)
分词器被标记化成独立的词。一个简单的分词器(tokenizer)可以根据空格或逗号将单词分开(这个在中文中不适用)。
- 标记过滤(token filters)
标记过滤可以修改词(例如将"Quick"转为小写),去掉词(例如停用词像"a"、"and"、"the"等等),或者增加词(例如同义词像"jump"和"leap")
由上面的图可以看出:Analyzer(分析器)由Tokenizer(分词器)和Filter(过滤器)组成。
常用的分析器有:
- standard analyzer:标准分析器
- simple analyzer:简单分析器,包含lower case tokenizer
- language analyzers:各语言的分词器
- 自定义分词器:可以指定一个tokenizer,0个、1个或多个Filter
在mapping中指定分析器
{
"field1" : {
"type" : "string",
"analyzer" : "string_lowercase"
}}
指定默认的分析器
{
"field1" : {
"type" : "string"
}}
不使用分析器
{
"field1" : {
"type" : "string",
"index" : "not_analyzed"
}}
本人用的是英文分词器:如下:
参考文档:
ES中的分词器