类似关系型数据库中每个字段都有对应的数据类型,例如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 域包含如下内容:

  1. The quick brown fox jumped over the lazy dog
  2. 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

布尔型: true 或者 false

boolean

整数: 123

long

浮点数: 123.45

double

字符串,有效日期: 2014-09-15

date

字符串: foo bar

string

这意味着如果通过“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) 映射和分析的更多相关文章

  1. elasticsearch的映射(mapping)和分析(analysis)

    转发自:http://blog.csdn.net/hzrandd/article/details/47128895 分析和分析器 分析(analysis)是这样一个过程: 首先,表征化一个文本块为适用 ...

  2. Elasticsearch mapping映射文件设置没有生效

    Elasticsearch mapping映射文件设置没有生效 问题背景 我们一般会预先创建 Elasticsearch index的 mapping.properties 文件(类似于MySQL中的 ...

  3. Elasticsearch入门教程(三):Elasticsearch索引&映射

    原文:Elasticsearch入门教程(三):Elasticsearch索引&映射 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文 ...

  4. ElasticSearch 嵌套映射和过滤器及查询

    ElasticSearch - 嵌套映射和过滤器 Because nested objects are indexed as separate hidden documents, we can’t q ...

  5. elasticsearch indices.recovery 流程分析(索引的_open操作也会触发recovery)——主分片recovery主要是从translog里恢复之前未写完的index,副分片recovery主要是从主分片copy segment和translog来进行恢复

    摘自:https://www.easyice.cn/archives/231 elasticsearch indices.recovery 流程分析与速度优化 目录 [隐藏] 主分片恢复流程 副本分片 ...

  6. ElasticSearch 线程池类型分析之SizeBlockingQueue

    ElasticSearch 线程池类型分析之SizeBlockingQueue 尽管前面写好几篇ES线程池分析的文章(见文末参考链接),但都不太满意.但从ES的线程池中了解到了不少JAVA线程池的使用 ...

  7. ElasticSearch 线程池类型分析之 ExecutorScalingQueue

    ElasticSearch 线程池类型分析之 ExecutorScalingQueue 在ElasticSearch 线程池类型分析之SizeBlockingQueue这篇文章中分析了ES的fixed ...

  8. ElasticSearch 线程池类型分析之 ResizableBlockingQueue

    ElasticSearch 线程池类型分析之 ResizableBlockingQueue 在上一篇文章 ElasticSearch 线程池类型分析之 ExecutorScalingQueue的末尾, ...

  9. ElasticSearch 5学习(9)——映射和分析(string类型废弃)

    在ElasticSearch中,存入文档的内容类似于传统数据每个字段一样,都会有一个指定的属性,为了能够把日期字段处理成日期,把数字字段处理成数字,把字符串字段处理成字符串值,Elasticsearc ...

随机推荐

  1. JS 作用域(执行环境)与作用链---JS 学习笔记(二)

    一  作用域(执行环境) 作用域:定义了变量和函数有权访问的其他数据,决定了他们各自的行为.--------<JS高级程序设计>4.2 好难理解啊~参考了参考尤克希的博客内容,大体上理解了 ...

  2. SAM宏观生态学空间分析帮助文档

    宏观生态学分析软件帮助文档: 引言: 该软件是由布鲁塞尔..大学开发,目的是提供一个综合的空间分析计算平台,主要针对的是宏观生态学数据.该软件可以从网站...上自由获取,该软件的主要特征以及发表在20 ...

  3. leecode第三百四十四题(反转字符串)

    class Solution { public: void reverseString(vector<char>& s) { int len=s.size(); char temp ...

  4. storybook配置之基本配置和webpack配置

    默认配置 Storybook有一个默认的适合(suits)大型项目开发的webpack配置,假如你使用react app,他类似于创建一个react app的配置,并经过调整(tweaked ),使其 ...

  5. vue版 文字滚动

    用法:<marque :text="bannerText"></marque> 下载

  6. [GXOI/GZOI2019]与或和

    考虑拆位,计算每一个二进制位的贡献. 问题转化为求一个01矩阵的全0/1的子矩形个数. 考虑计算以第i行第j列为右下角的合法子矩形个数. 发现合法的左上角范围向左是单调下降的. 可以用一个单调栈来维护 ...

  7. C++之标准库map

    目录 1.成员函数 2.元素访问 3.迭代器Iterators(C++ 11) 4.容量Capacity 5.修改函数(C++ 11和C++ 17) 6.查找表Lookup 7.观察Observers ...

  8. php 根据输入的参数,获取上季度最后一个月的时间

    public function getTime( $time ='2017-06-01 00:00:00'){ $month = date('m',strtotime($time)); $season ...

  9. 菜鸟脱壳之脱壳的基础知识(六)——手动查找IAT和修复Dump的程序

    前面讲了如何寻找OEP和脱壳,有的时候,Dump出来的时候不能正常运行,是因为还有一个输入表没有进行处理,一些加密壳会在IAT加密上面大做文章,用HOOK - API的外壳地址来代替真是的IAT的地址 ...

  10. SQL server 数据库的版本为661,无法打开,此服务器只支持655版及更低版本。不支持降级路径

    亲测有效. 解决方案:造成这个错误是因为把本地的SQL Server (MSSQLSERVER)服务给禁止了,而把 SQL Server (SQLEXPRESS)服务给启动了,因为这样子,本来应该在数 ...