Elasticsearch整理笔记(五)

es6以上版本需要注意的:

1.elasticsearch-head 在连接6.x以上版本时会报406错误:

Content-Type header [application/x-www-form-urlencoded] is not supported

原因:

6.x 版本的ES严格控制了Content-Type 问题,application/x-www-form-urlencoded不支持JSON格式的内容体,所以需要修改

解决办法:

进入head插件安装目录->elasticsearch-head文件夹->vendor.js文件

修改两处:

1. 6886行 contentType: "application/x-www-form-urlencoded"
    改成 contentType: "application/json;charset=UTF-8" 
2. 7574行 var inspectData = s.contentType === "application/x-www-form-urlencoded" && 
    改成 var inspectData = s.contentType === "application/json;charset=UTF-8" &&

 

2.type

从Elasticsearch的第一个发布版本以来,每一个文档都被存储在一个单独的索引里,并被赋予了一个type,一个映射类型代表着一个被索引的文档或实体的类型,例如,一个twitter索引可能有一个user类型和tweet类型。

每种映射类型都有他自己的字段,所以user类型可能有一个full_name字段,一个user_name字段和一个email字段,而一个tweet类型可能有一个content字段,一个tweet_at字段,和user类型一样一个user_name字段。

每一个文档类型都有一个_type元字段来存储type名称,并且根据URL里指定的类型名称,查询(搜索)被限定在一个或多个类型(type)里

GET twitter/user,tweet/_search
{
  "query": {
    "match": {
      "user_name": "kimchy"
    }
  }
}

_type字段用来和文档的_id字段联合生成_uid字段,所以有着相同_id的不同类型的文档可以存在同一个索引里。类型也用来建立文档间的父子关系,所以question类型的文档可能是anser类型文档的父文档。

起初,我们说"索引"和关系数据库的“库”是相似的,“类型”和“表”是对等的。
这是一个不正确的对比,导致了不正确的假设。在关系型数据库里,"表"是相互独立的,一个“表”里的列和另外一个“表”的同名列没有关系,互不影响。但在类型里字段不是这样的。

在一个Elasticsearch索引里,所有不同类型的同名字段内部使用的是同一个lucene字段存储。也就是说,上面例子中,user类型的user_name字段和tweet类型的user_name字段是存储在一个字段里的,两个类型里的user_name必须有一样的字段定义。

这可能导致一些问题,例如你希望同一个索引中"deleted"字段在一个类型里是存储日期值,在另外一个类型里存储布尔值。

最后,在同一个索引中,存储仅有小部分字段相同或者全部字段都不相同的文档,会导致数据稀疏,影响Lucene有效压缩数据的能力。

所以6.X强制规定一个索引只能有一个类型,而7.X直接移除类型的概念。

但是存在一个问题,在ES5.X版本,借助父子文档实现多表关联,类似数据库中Join的功能;实现的核心是借助于ES5.X支持1个索引(index)下多个类型(type)。而ES6.X版本,由于每个索引下面只支持单一的类型(type)。如何实现类似于mysql多个表的关联呢?——Elasticsearch 6.X 新类型Join

详细请看官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/current/parent-join.html

3.特殊字符&keyword查询

es5版本对于不分词keyword的字段是可以直接用term、wildcard等查询的,但是在es6以上就会发现查询是无效的,即使不分词,精准查询term也会查询出不精准的数据,且“-”“+”等特殊字符无法参与搜索条件,转义也无效。

{
	"query": {
		"bool": {
			"filter": [{
				"term": {
					"user_id":"user-x"
				}
			}]
		}
	}
}

上述查询是无法实现查找“user_id"字段为“user-x”值的。

{
	"query": {
		"bool": {
			"filter": [{
				"term": {
					"user_id":"user"
				}
			}]
		}
	}
}

上述查询反而可以把user-x查找出来。

原因:

es的5.0版本后,把string类型分成了text和keyword两种类型,前者会先被分词处理再进行索引,而后者不会,完整字符串直接成为索引。

官方说明:

Keyword datatype
A field to index structured content such as email addresses, hostnames, status codes, zip codes or tags.
They are typically used for filtering (Find me all blog posts where status is published), for sorting, and for aggregations. Keyword fields are only searchable by their exact value.
If you need to index full text content such as email bodies or product descriptions, it is likely that you should rather use a text field.

而不知道为什么,6.x版本后的keyword并非如此,原有的文本型数据依然会被分词处理,只是会额外建立一个keyword属性来保留完整字符。

当我们搜索条件为不分词的原数据时候,需要在原有的key后面加上.keyword,通过对比key.keyword来实现精准匹配的效果。

{
	"query": {
		"bool": {
			"filter": [{
				"term": {
					"user_id.keyword":"user-x"
				}
			}]
		}
	}
}

这个设计简直反人类,我也没有想到如此设计会有什么优点。且会有大量的无用分词数据浪费资源,所以说,不需要分词的话还有没有必要使用es?这是一个深入灵魂的问题。

猜你喜欢

转载自blog.csdn.net/sm9sun/article/details/109070081