elasticsearch(6) 映射和分析
类似关系型数据库中每个字段都有对应的数据类型,例如nvarchar、int、date等等,elasticsearch也会将文档中的字段映射成对应的数据类型,这一映射可以使ES自动生成的,也是可以由我们自定义的。不同的映射关系是会影响到我们的搜索查询功能。
GET /_search?q= # results
GET /_search?q=-- # results !
GET /_search?q=date:-- # result
GET /_search?q=date: # results !
分析上面的查询语句,我们可以发现一个很奇怪的现象。为什么通过q=2014可以查到12条结果,但通过date字段查询年份q=date:2014却没有结果呢?我们推测就是因为不同的字段映射的类型不同而导致的。
- 使用分析工具
通过_mapping api可以分析类型的映射
GET /gb/_mapping/tweet
{
"gb": {
"mappings": {
"tweet": {
"properties": {
"date": {
"type": "date",
"format": "strict_date_optional_time||epoch_millis"
},
"name": {
"type": "string"
},
"tweet": {
"type": "string"
},
"user_id": {
"type": "long"
}
}
}
}
}
}
我们可以看到date字段是date类型的,而q=2014查询的是_all字段,我们知道这个字段是String类型的。我们可能会猜测 date
字段和 string
字段 索引方式不同,所以搜索结果也不一样。
但实际上虽然不同的数据类型的索引方式会有所不同,但最大的区别是一个是代表精确值的字段(包括String类型),另一个是代表全文的字段。这个区别非常重要,这正是ES和其他关系型数据库最大的不同。ES会将全文域的所有词条形成倒排索引,这也是ES搜索的基础。
- 倒排索引
elsaticsearch使用一种称为倒排索引的结构,它适用于快速的全文搜索。一个倒排索引由文档中所有不重复词的列表构成,对于其中每个词,有一个包含它的文档列表。
例如,假设我们有两个文档,每个文档的 content
域包含如下内容:
- The quick brown fox jumped over the lazy dog
- Quick brown foxes leap over lazy dogs in summer
为了创建倒排索引,我们首先将每个文档的 content
域拆分成单独的 词(我们称它为 词条
或 tokens
),创建一个包含所有不重复词条的排序列表,然后列出每个词条出现在哪个文档。结果如下所示:
Term Doc_1 Doc_2
-------------------------
Quick | | X
The | X |
brown | X | X
dog | X |
dogs | | X
fox | X |
foxes | | X
in | | X
jumped | X |
lazy | X | X
leap | | X
over | X | X
quick | X |
summer | | X
the | X |
------------------------
如果我们想要搜索 quick brown
,我们只需要查找包含每个词条的文档:
Term Doc_1 Doc_2
-------------------------
brown | X | X
quick | X |
------------------------
Total | |
由上图可得知,匹配的文档有两个,但是第一个文档要比第二个匹配度更好。但这也引发出了一些问题。
对于一个搜索操作来说:
1、用户可能不关心词条的大小写,Quick和quick可能是一样的
2、由于词法的变化,例如单复数的变化,对于用户来说可能也是不关心的,例如dog和dogs
3、同义词,一些同义词尽管不同,但实际上表达的含义是相同的,我们希望能够匹配出来。
解决方案:
对于输入和输出事先做预处理,也就是在倒排索引前对文档统一处理,例如把Quick统一成quick,把dogs统一成dog。搜索时,对搜索的内容也做统一处理,例如Quick dogs转化成quick dog。这样通过倒排索引就可以解决上面几个问题,优化搜索。这个过程就是分析。
- 分析和分析器
所谓分析器实际上是把三个功能封装在了一个包里
1、字符过滤器
首先,字符串按顺序通过每个字符过滤器。他们的任务是在分词前整理字符串。一个字符过滤器可以用来去掉HTML,或者将 &
转化成 `and`。
2、分词器
字符串被分词器分为单个的词条。一个简单的分词器遇到空格和标点的时候,可能会将文本拆分成词条。
3、Token过滤器
词条按顺序通过每个Token过滤器。这个过程可能会改变词条(例如,小写化 Quick
),删除词条(例如, 像 a,and,the
等无用词),或者增加词条(例如,像 jump
和 leap
这种同义词)
- 内置分析器
ES附带了可以直接使用的预包装的分析器
示例文本
"Set the shape to semi-transparent by calling set_trans(5)"
1、标准分析器
标准分析器是Elasticsearch默认使用的分析器。它是分析各种语言文本最常用的选择。它根据Unicode联盟定义的单词边界划分文本。删除绝大部分标点。最后,将词条小写。
set, the, shape, to, semi, transparent, by, calling, set_trans,
2、简单分析器
简单分析器在任何不是字母的地方分隔文本,将词条小写。
set, the, shape, to, semi, transparent, by, calling, set, trans
3、空格分析器
空格分析器在任何不适字母的地方分割文本,将词条小写。
Set, the, shape, to, semi-transparent, by, calling, set_trans()
4、语言分析器
特定语言分析器可用于很多语言。它们可以考虑指定语言的特点。例如, 英语
分析器附带了一组英语无用词(常用单词,例如 and
或者the
,它们对相关性没有多少影响),它们会被删除。 由于理解英语语法的规则,这个分词器可以提取英语单词的词干。
set, shape, semi, transpar, call, set_tran,
这里set_trans变为了set_tran,calling变为了call
- 测试分析器
有些时候很难理解分词的过程和实际被存储到索引中的词条,你可以使用 analyze
API 来看文本是如何被分析的。在消息体里,指定分析器和要分析的文本:
GET 127.0.0.1:9200/_analyze
{
"analyzer": "standard",
"text": "our Fingertips owns the power of changing the world"
}
响应
{
"tokens": [
{
"token": "our",
"start_offset": ,
"end_offset": ,
"type": "<ALPHANUM>",
"position":
},
{
"token": "fingertips",
"start_offset": ,
"end_offset": ,
"type": "<ALPHANUM>",
"position":
},
{
"token": "owns",
"start_offset": ,
"end_offset": ,
"type": "<ALPHANUM>",
"position":
},
{
"token": "the",
"start_offset": ,
"end_offset": ,
"type": "<ALPHANUM>",
"position":
},
{
"token": "power",
"start_offset": ,
"end_offset": ,
"type": "<ALPHANUM>",
"position":
},
{
"token": "of_changing",
"start_offset": ,
"end_offset": ,
"type": "<ALPHANUM>",
"position":
},
{
"token": "the",
"start_offset": ,
"end_offset": ,
"type": "<ALPHANUM>",
"position":
},
{
"token": "world",
"start_offset": ,
"end_offset": ,
"type": "<ALPHANUM>",
"position":
}
]
}
从中我们可以看到分析器是怎么帮我们分词的。token
是实际存储到索引中的词条。 position
指明词条在原始文本中出现的位置。 start_offset
和end_offset
指明字符在原始字符串中的位置。
- 核心简单域类型
elasticsearch支持一下简单域类型
1、字符串:string
2、整数:byte,short,integer,long
3、浮点型:float,double
4、布尔型:boolean
5、日期:date
当你索引一个包含新域的文档(之前未曾出现), Elasticsearch 会使用动态映射,通过JSON中基本数据类型,尝试猜测域类型,使用如下规则:
JSON type |
域 type |
布尔型: |
|
整数: |
|
浮点数: |
|
字符串,有效日期: |
|
字符串: |
|
这意味着如果通过“123”索引一个数字,那么它会被映射成为string,但如果这个域已经是long,那么ES会尝试将这个字符串转化为long,如果无法转化,则抛出一个异常。
- 自定义域映射
自定义映射可以做到
1、全文字符串域和精确值字符串域的区别
2、使用特定的语言分析器
3、优化域以适应部分匹配
4、指定自定义数据格式
域属性:
- type
域最重要的属性是type.对于不是string的域,一般只需要设置type
{
"number_of_clicks": {
"type": "integer"
}
}
默认, string
类型域会被认为包含全文。就是说,它们的值在索引前,会通过 一个分析器,针对于这个域的查询在搜索前也会经过一个分析器。
- index
index属性控制了怎样所以字符串,值可以为:
1、analyzed
首先分析字符串,然后索引它。换句话说,以全文索引这个域。
2、not_analyzed
索引这个域,所以可以搜索到它,但索引指定的精确值。不对它进行分析。
3、no
这个域不会被搜索到。
{
"tag": {
"type": "string",
"index": "not_analyzed"
}
}
- analyzer
对于 analyzed
字符串域,用 analyzer
属性指定在搜索和索引时使用的分析器。默认, Elasticsearch 使用 standard
分析器, 但你可以指定一个内置的分析器替代它,例如 whitespace
、 simple
和 english:
{
"tweet": {
"type": "string",
"analyzer": "english"
}
}
更新映射
首次 创建一个索引的时候,可以指定类型的映射。你也可以使用 /_mapping
为新类型(或者为存在的类型更新映射)增加映射。
注意:尽管你可以增加一个已经存在的映射,但无法修改存在的域映射。如果一个域的映射已经存在,那么该域的数据可能已经被索引。如果你意图修改这个域的映射,索引的数据可能会出错,不能被正常的搜索。
- 创建索引时指定映射
PUT /gb
{
"mappings": {
"tweet" : {
"properties" : {
"tweet" : {
"type" : "string",
"analyzer": "english"
},
"date" : {
"type" : "date"
},
"name" : {
"type" : "string"
},
"user_id" : {
"type" : "long"
}
}
}
}
}
这段代码指定了tweet类型的映射,把tweet属性使用english分析器,是一个全文string类型。date为日期类型,name为全文string类型使用standard分析器,user_id是长整型。
- 新增一个属性,并指定映射
PUT /gb/_mapping/tweet
{
"properties" : {
"tag" : {
"type" : "string",
"index": "not_analyzed"
}
}
}
新增了一个tag属性,为一个精确值string类型,即不对这个字段作分析
我们来测试一下
GET /gb/_analyze?field=tweet&text=Black-cats GET /gb/_analyze?field=tag&text=Black-cats
可以看到对于tweet属性来说,索引为black和cat,而对于Black-cat 来说索引为Black-cat
elasticsearch(6) 映射和分析的更多相关文章
- elasticsearch的映射(mapping)和分析(analysis)
转发自:http://blog.csdn.net/hzrandd/article/details/47128895 分析和分析器 分析(analysis)是这样一个过程: 首先,表征化一个文本块为适用 ...
- Elasticsearch mapping映射文件设置没有生效
Elasticsearch mapping映射文件设置没有生效 问题背景 我们一般会预先创建 Elasticsearch index的 mapping.properties 文件(类似于MySQL中的 ...
- Elasticsearch入门教程(三):Elasticsearch索引&映射
原文:Elasticsearch入门教程(三):Elasticsearch索引&映射 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文 ...
- ElasticSearch 嵌套映射和过滤器及查询
ElasticSearch - 嵌套映射和过滤器 Because nested objects are indexed as separate hidden documents, we can’t q ...
- elasticsearch indices.recovery 流程分析(索引的_open操作也会触发recovery)——主分片recovery主要是从translog里恢复之前未写完的index,副分片recovery主要是从主分片copy segment和translog来进行恢复
摘自:https://www.easyice.cn/archives/231 elasticsearch indices.recovery 流程分析与速度优化 目录 [隐藏] 主分片恢复流程 副本分片 ...
- ElasticSearch 线程池类型分析之SizeBlockingQueue
ElasticSearch 线程池类型分析之SizeBlockingQueue 尽管前面写好几篇ES线程池分析的文章(见文末参考链接),但都不太满意.但从ES的线程池中了解到了不少JAVA线程池的使用 ...
- ElasticSearch 线程池类型分析之 ExecutorScalingQueue
ElasticSearch 线程池类型分析之 ExecutorScalingQueue 在ElasticSearch 线程池类型分析之SizeBlockingQueue这篇文章中分析了ES的fixed ...
- ElasticSearch 线程池类型分析之 ResizableBlockingQueue
ElasticSearch 线程池类型分析之 ResizableBlockingQueue 在上一篇文章 ElasticSearch 线程池类型分析之 ExecutorScalingQueue的末尾, ...
- ElasticSearch 5学习(9)——映射和分析(string类型废弃)
在ElasticSearch中,存入文档的内容类似于传统数据每个字段一样,都会有一个指定的属性,为了能够把日期字段处理成日期,把数字字段处理成数字,把字符串字段处理成字符串值,Elasticsearc ...
随机推荐
- JS 作用域(执行环境)与作用链---JS 学习笔记(二)
一 作用域(执行环境) 作用域:定义了变量和函数有权访问的其他数据,决定了他们各自的行为.--------<JS高级程序设计>4.2 好难理解啊~参考了参考尤克希的博客内容,大体上理解了 ...
- SAM宏观生态学空间分析帮助文档
宏观生态学分析软件帮助文档: 引言: 该软件是由布鲁塞尔..大学开发,目的是提供一个综合的空间分析计算平台,主要针对的是宏观生态学数据.该软件可以从网站...上自由获取,该软件的主要特征以及发表在20 ...
- leecode第三百四十四题(反转字符串)
class Solution { public: void reverseString(vector<char>& s) { int len=s.size(); char temp ...
- storybook配置之基本配置和webpack配置
默认配置 Storybook有一个默认的适合(suits)大型项目开发的webpack配置,假如你使用react app,他类似于创建一个react app的配置,并经过调整(tweaked ),使其 ...
- vue版 文字滚动
用法:<marque :text="bannerText"></marque> 下载
- [GXOI/GZOI2019]与或和
考虑拆位,计算每一个二进制位的贡献. 问题转化为求一个01矩阵的全0/1的子矩形个数. 考虑计算以第i行第j列为右下角的合法子矩形个数. 发现合法的左上角范围向左是单调下降的. 可以用一个单调栈来维护 ...
- C++之标准库map
目录 1.成员函数 2.元素访问 3.迭代器Iterators(C++ 11) 4.容量Capacity 5.修改函数(C++ 11和C++ 17) 6.查找表Lookup 7.观察Observers ...
- php 根据输入的参数,获取上季度最后一个月的时间
public function getTime( $time ='2017-06-01 00:00:00'){ $month = date('m',strtotime($time)); $season ...
- 菜鸟脱壳之脱壳的基础知识(六)——手动查找IAT和修复Dump的程序
前面讲了如何寻找OEP和脱壳,有的时候,Dump出来的时候不能正常运行,是因为还有一个输入表没有进行处理,一些加密壳会在IAT加密上面大做文章,用HOOK - API的外壳地址来代替真是的IAT的地址 ...
- SQL server 数据库的版本为661,无法打开,此服务器只支持655版及更低版本。不支持降级路径
亲测有效. 解决方案:造成这个错误是因为把本地的SQL Server (MSSQLSERVER)服务给禁止了,而把 SQL Server (SQLEXPRESS)服务给启动了,因为这样子,本来应该在数 ...