elasticsearch:5.4.3
虚拟机:centos7
kibana:5.4.3
操作系统:win7
本篇属于个人学习笔记奥,不做教程
存储数据到elasticsearch
的行为叫做索引
。
你也许已经注意到 索引 这个词在 Elasticsearch 语境中包含多重意思, 所以有必要做一点儿说明:
索引(名词):
如前所述,一个 索引 类似于传统关系数据库中的一个 数据库 ,是一个存储关系型文档的地方。 索引 (index) 的复数词为 indices 或 indexes 。
索引(动词):
索引一个文档 就是存储一个文档到一个 索引 (名词)中以便它可以被检索和查询到。这非常类似于 SQL 语句中的 INSERT 关键词,除了文档已存在时新文档会替换旧文档情况之外。
倒排索引:
关系型数据库通过增加一个 索引 比如一个 B树(B-tree)索引 到指定的列上,以便提升数据检索速度。Elasticsearch 和 Lucene 使用了一个叫做 倒排索引 的结构来达到相同的目的。
+
默认的,一个文档中的每一个属性都是 被索引 的(有一个倒排索引)和可搜索的。一个没有倒排索引的属性是不能被搜索到的。我们将在 倒排索引 讨论倒排索引的更多细节。
短语搜索就是精准匹配。
GET megacorp/employee/_search
{
"query": {
"match_phrase": {
"about": "rock climbing"
}
}
}
这里就是使用match_phrase
过滤器进行精准匹配字段about
为rock climbing
的文档。
这个fielddata
是在官网Mapping
章节中。我自己翻译:
译文:
默认情况下,大部分字段都是被索引的(有个倒排索引),以使得他们可以被搜索。
然而,在脚本中排序、聚合和访问字段的值,需要不同的搜索访问模式。
搜索需要回答的问题是“哪些文档包含这些搜索的内容?”
,而排序和聚合需要回答的问题是“这个文档中这个字段的值是什么?”
大部分字段都可以使用index-time
,磁盘上的doc_values
用于这个数据的访问模式;
然而,text
字段不支持doc_values
。
代替的是,text
字段使用一个叫做fielddata
的数据结构,该数据结构含义是查询时内存数据结构。该数据结构是按需求首次构建在一个被用于聚合、排序和在脚本的字段上。
它是通过读取从磁盘每段的整个倒排索引来构建的,倒排搜索的内容
<->文档
关系,其存储在jvm
堆上的内存上。
text
字段默认是没有开启的fielddata
会消耗堆上大量的空间,特别是在加载高基数的text
字段时。
一旦fielddata
加载到了堆上,它将保持在段的生命周期里。此外,加载fielddata
是一个昂贵的过程,它会使得用户遇到延迟命中。这就是为什么默认是禁止的原因。
如果你尝试在text
字段上进行排序、聚合和在脚本中访问值,你将看到这个异常:
Fielddata is disabled on text fields by default. Set fielddata=true on [your_field_name] in order to load fielddata in memory by uninverting the inverted index. Note that this can however use significant memory.
在你启动fielddata
之前,考虑为什么使用text
字段用于聚合、排序或在脚本中。这样做通过是没有意义的。
在索引之前应该分析文本字段以便于通过搜索new
或者york
能够搜索到new york
这样的值。当你想要一个名为new york
值(桶)时,在这个字段上的聚合操作terms
将会返回一个new
值(桶:bucket)和york
值(桶:bucket)。
说明:
bucket
是elasticsearch
执行聚合操作返回的结果值。其实就是数组。
比如我执行:
GET megacorp/employee/_search
{
"aggs": {
"all_int": {
"terms": {"field": "interests"},//terms
"aggs": {
"avg_age": {
"avg": {
"field": "age"
}
}
}
}
}
}
效果如下:
"aggregations": {
"all_int": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [//buckets
{
"key": "music",
"doc_count": 2,
"avg_age": {
"value": 28.5
}
},
{
"key": "forestry",
"doc_count": 1,
"avg_age": {
"value": 35
}
},
{
"key": "sports",
"doc_count": 1,
"avg_age": {
"value": 25
}
}
]
}
}
相反,你应该有一个文本字段用于全文搜索,和一个未被分析的关键字字段,其中doc_values
启用聚合。如下:
PUT my_index
{
"mappings": {
"my_type": {
"properties": {
"my_field": { ①
"type": "text",
"fields": {
"keyword": { ②
"type": "keyword"
}
}
}
}
}
}
}
①:使用my_field
字段用于搜索。
②:使用my_field.keyword
字段用于聚合、排序和脚本中使用。
text
字段上启用fielddata你可以在已有的text
字段使用PUT mapping API
启用fielddata
,如下所示:
PUT my_index/_mapping/my_type
{
"properties": {
"my_field": { ①
"type": "text",
"fielddata": true
}
}
}
①:你给my_field
指定的映射,应该是由已有的字段映射和fielddata
参数组成。
注意:
fielddata.*
参数设置必须在同一索引中相同字段名保持一致。
他可以使用PUT mapping API
更新已有的值。
在官网教程中开启fielddata
方法:
这段代码目的是为了,为了既能搜索,又能聚合目的。
PUT megacorp/_mapping/employee
{
"properties": {
"interests":{
"type": "text",
"fields": {
"keyword":{
"type": "keyword"
}
}
}
}
}
开启fielddata
:
PUT megacorp/_mapping/employee
{
"properties": {
"interests":{
"type": "text",
"fielddata": true
}
}
}
这里只是说下小区别:
插入文档时,如果没有指定_id
,相应elasticsearch
自动生成的话,需要使用post
POST website/blog
{
"title": "My third blog entry",
"text": "Third still trying this out...",
"date": "2017/07/05"
}
结果:
{
"_index": "website",
"_type": "blog",
"_id": "AV0Qv0wO-S86jJ72I7lo",//这个id是自动生成的
"_version": 1,
"result": "created",
"_shards": {
"total": 2,
"successful": 2,
"failed": 0
},
"created": true
}
如果使用put
,并没有指定_id
的话:
PUT website/blog
{
"title": "My third blog entry",
"text": "Third still trying this out...",
"date": "2017/07/05"
}
会报错:
No handler found for uri [/website/blog] and method [PUT]