类型在Elasticsearch中表示一组相似的文档。类型由一个名称(比如user或blogpost)和一个类似数据库表结构的映射组成,描述了文档中可能包含的每个字段的属性,数据类型(比如string、integer或date),和是否这些字段需要被Lucene索引或储存。
Lucene如何处理文档
Lucene中,一个文档由一组简单地键值对组成,一个字段至少需要有一个值,但是任何字段都可以有多个值。类似的,一个单独的字符串可能在分析过程中被转换成多个值。Lucene不关心这些值是字符串、数字或日期,所有的制都被当成不透明字节。
当我们在Lucene中索引一个文档时,每个字段的值都被加到相关字段的倒排索引中。你也可以选择将原始数据存储起来以备今后取回。
类型是怎么实现的
Elasticsearch类型是在这个简单基础上实现的。一个索引可能包含多个类型,每个类型有各自的映射和文档,保存在同一个索引中。
因为Lucene没有文档类型的概念,每个文档的类型名被存储在一个叫 _type 的元数据字段上。当我们搜索一种特殊类型的文档时,Elasticsearch简单地通过 _type 字段来过滤出这些文档。
Lucene同样没有映射的概念。映射是Elasticsearch将复杂JSON文档映射成Lucene需要的扁平化数据的方式。
例如,user类型中name字段的映射声明这个字段是一个string类型,在被假如倒排索引之前,它的数据需要通过 whitespace 分析器来分析。
预防类型陷阱
事实上不同类型的文档可以被加到同一个索引里带来了一些预想不到的困难。
想象一下我们的索引中有两种类型:blog_en 表示英语版的博客, blog_es 表示西班牙语版的博客。两种类型都有 title 字段,但是其中一种类型使用 english 分析器,另
一种使用 spanish分析器。
使用下面的查询就会遇到问题:
GET /_search
{
"query" : {
"match" : {
"match" : {
"title" : "The quick brown fox"
}
}
}
}
我们在两种类型中搜索title 字段,首先需要分析查询语句,但是应该使用哪种分析器呢,spanish 还是 english ?
Elasticsearch会采用第一个被找到的title字段使用的分析器,这对于这个字段的文档来说是正确的,但对另一个来说却是错误的。
我们可以通过给字段取不同的名字来避免这种错误——比如,用 title_en 和 title_es。或者在查询中明确包含各自的类型名。
GET /_search
{
"query" : {
"multi_match" : {
"query" : "The quick brown fox",
"fields" : [ "blog_en.title" , "blog_es.title" ]
}
}
}
注意:multi_match 查询在多个字段上执行 match查询并一起返回结果。
新的查询中 english分析器用于blog_en.title字段,spanish 分析器用于blog_es.title字段,然后通过综合得分组合两种字段的结果。
这种办法对具有相同数据类型的字段有帮助,但是想象一下如果你将下面两个文档加入同一个索引,会发生什么:
- 类型:user
- 类型:event