精确值 VS 全文
当摆弄索引里面的数据时,我们发现一些奇怪的事情。一些事情看起来被打乱了:在我们的索引中有12条推文,其中只有一条包含日期 2014-09-15
,但是看一看下面查询命中的 总数 (total
):
GET /_search?q=2014 # 12 results
GET /_search?q=2014-09-15 # 12 results !
GET /_search?q=date:2014-09-15 # 1 result
GET /_search?q=date:2014 # 0 results !
为什么在 _all 字段查询日期返回所有推文,而在 date
字段只查询年份却没有返回结果?为什么我们在 _all
字段和 date
字段的查询结果有差别?
推测起来,这是因为数据在 _all
字段与 date
字段的索引方式不同。所以,通过请求 gb
索引中 tweet
类型的映射(或模式定义),让我们看一看 Elasticsearch 是如何解释我们文档结构的:
GET /gb/_mapping/tweet
从ES 7.0.0 开始,Type就被移除了(变成了_doc
),如果像上面那样去GET,将会得到一个报错:
{
"error": {
"root_cause": [
{
"type": "illegal_argument_exception",
"reason": "Types cannot be provided in get mapping requests, unless include_type_name is set to true."
}
],
"type": "illegal_argument_exception",
"reason": "Types cannot be provided in get mapping requests, unless include_type_name is set to true."
},
"status": 400
}
在此用GET /gb/_mapping/
进行获取文档结构:
{
"gb": {
"mappings": {
"properties": {
"date": {
"type": "date",
"format": "strict_date_optional_time||epoch_millis"
},
"name": {
"type": "string"
},
"tweet": {
"type": "string"
},
"user_id": {
"type": "long"
}
}
}
}
}
基于对字段类型的猜测, Elasticsearch 动态为我们产生了一个映射。这个响应告诉我们 date
字段被认为是 date
类型的。由于 _all
是默认字段,所以没有提及它。但是我们知道 _all
字段是 string
类型的。
所以 date
字段和 string
字段索引方式不同,因此搜索结果也不一样。这完全不令人吃惊。你可能会认为核心数据类型 strings
、numbers
、Booleans
和 dates
的索引方式有稍许不同。没错,他们确实稍有不同。
但是,到目前为止,最大的差异在于代表 精确值
(它包括 string 字段)的字段和代表 全文
的字段。这个区别非常重要——它将搜索引擎和所有其他数据库区别开来。
注:
5.X以上版本没有string
类型了,换成了text
和keyword
作为字符串类型!!!
Elasticsearch 中的数据可以概括的分为两类:精确值和全文。
精确值:如它们听起来那样精确。例如日期或者用户 ID,但字符串也可以表示精确值,例如用户名或邮箱地址。对于精确值来讲,Foo
和 foo
是不同的,2014
和 2014-09-15
也是不同的。
全文: 是指文本数据(通常以人类容易识别的语言书写),例如一个推文的内容或一封邮件的内容。
精确值很容易查询。要么匹配查询,要么不匹配。这种查询很容易用 SQL 表示:
WHERE name = "John Smith"
AND user_id = 2
AND date > "2014-09-15"
查询全文数据要微妙的多。我们问的不只是“这个文档匹配查询吗”,而是“该文档匹配查询的程度有多大?”换句话说,该文档与给定查询的相关性如何?
我们很少对全文类型的域做精确匹配。相反,我们希望在文本类型的域中搜索。不仅如此,我们还希望搜索能够理解我们的 意图 :
- 搜索 UK ,会返回包含 United Kindom 的文档。
- 搜索 jump ,会匹配 jumped , jumps , jumping ,甚至是 leap 。
- 搜索 johnny walker 会匹配 Johnnie Walker , johnnie depp 应该匹配 Johnny Depp 。
- fox news hunting 应该返回福克斯新闻( Foxs News )中关于狩猎的故事,同时, fox hunting news 应该返回关于猎狐的故事。
为了促进这类在全文域中的查询,Elasticsearch 首先 分析 文档,之后根据结果创建 倒排索引 。