类似关系型数据库中每个字段都有对应的数据类型,例如nvarchar、int、date等等,elasticsearch也会将文档中的字段映射成对应的数据类型,这一映射可以使ES自动生成的,也是可以由我们自定义的。不同的映射关系是会影响到我们的搜索查询功能。

  1. GET /_search?q= # results
  2. GET /_search?q=-- # results !
  3. GET /_search?q=date:-- # result
  4. GET /_search?q=date: # results !

分析上面的查询语句,我们可以发现一个很奇怪的现象。为什么通过q=2014可以查到12条结果,但通过date字段查询年份q=date:2014却没有结果呢?我们推测就是因为不同的字段映射的类型不同而导致的。

  • 使用分析工具

通过_mapping api可以分析类型的映射

  1. GET /gb/_mapping/tweet
  1. {
  2. "gb": {
  3. "mappings": {
  4. "tweet": {
  5. "properties": {
  6. "date": {
  7. "type": "date",
  8. "format": "strict_date_optional_time||epoch_millis"
  9. },
  10. "name": {
  11. "type": "string"
  12. },
  13. "tweet": {
  14. "type": "string"
  15. },
  16. "user_id": {
  17. "type": "long"
  18. }
  19. }
  20. }
  21. }
  22. }
  23. }

我们可以看到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),创建一个包含所有不重复词条的排序列表,然后列出每个词条出现在哪个文档。结果如下所示:

  1. Term Doc_1 Doc_2
  2. -------------------------
  3. Quick | | X
  4. The | X |
  5. brown | X | X
  6. dog | X |
  7. dogs | | X
  8. fox | X |
  9. foxes | | X
  10. in | | X
  11. jumped | X |
  12. lazy | X | X
  13. leap | | X
  14. over | X | X
  15. quick | X |
  16. summer | | X
  17. the | X |
  18. ------------------------

如果我们想要搜索 quick brown ,我们只需要查找包含每个词条的文档:

  1. Term Doc_1 Doc_2
  2. -------------------------
  3. brown | X | X
  4. quick | X |
  5. ------------------------
  6. 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附带了可以直接使用的预包装的分析器

示例文本

  1. "Set the shape to semi-transparent by calling set_trans(5)"

1、标准分析器

标准分析器是Elasticsearch默认使用的分析器。它是分析各种语言文本最常用的选择。它根据Unicode联盟定义的单词边界划分文本。删除绝大部分标点。最后,将词条小写。

  1. set, the, shape, to, semi, transparent, by, calling, set_trans,

2、简单分析器

简单分析器在任何不是字母的地方分隔文本,将词条小写。

  1. set, the, shape, to, semi, transparent, by, calling, set, trans

3、空格分析器

空格分析器在任何不适字母的地方分割文本,将词条小写。

  1. Set, the, shape, to, semi-transparent, by, calling, set_trans()

4、语言分析器

特定语言分析器可用于很多语言。它们可以考虑指定语言的特点。例如, 英语分析器附带了一组英语无用词(常用单词,例如 and 或者the,它们对相关性没有多少影响),它们会被删除。 由于理解英语语法的规则,这个分词器可以提取英语单词的词干。

  1. set, shape, semi, transpar, call, set_tran,

这里set_trans变为了set_tran,calling变为了call

  • 测试分析器

有些时候很难理解分词的过程和实际被存储到索引中的词条,你可以使用 analyze API 来看文本是如何被分析的。在消息体里,指定分析器和要分析的文本:

GET 127.0.0.1:9200/_analyze

  1. {
  2. "analyzer": "standard",
  3. "text": "our Fingertips owns the power of changing the world"
  4. }

响应

  1. {
  2. "tokens": [
  3. {
  4. "token": "our",
  5. "start_offset": ,
  6. "end_offset": ,
  7. "type": "<ALPHANUM>",
  8. "position":
  9. },
  10. {
  11. "token": "fingertips",
  12. "start_offset": ,
  13. "end_offset": ,
  14. "type": "<ALPHANUM>",
  15. "position":
  16. },
  17. {
  18. "token": "owns",
  19. "start_offset": ,
  20. "end_offset": ,
  21. "type": "<ALPHANUM>",
  22. "position":
  23. },
  24. {
  25. "token": "the",
  26. "start_offset": ,
  27. "end_offset": ,
  28. "type": "<ALPHANUM>",
  29. "position":
  30. },
  31. {
  32. "token": "power",
  33. "start_offset": ,
  34. "end_offset": ,
  35. "type": "<ALPHANUM>",
  36. "position":
  37. },
  38. {
  39. "token": "of_changing",
  40. "start_offset": ,
  41. "end_offset": ,
  42. "type": "<ALPHANUM>",
  43. "position":
  44. },
  45. {
  46. "token": "the",
  47. "start_offset": ,
  48. "end_offset": ,
  49. "type": "<ALPHANUM>",
  50. "position":
  51. },
  52. {
  53. "token": "world",
  54. "start_offset": ,
  55. "end_offset": ,
  56. "type": "<ALPHANUM>",
  57. "position":
  58. }
  59. ]
  60. }

从中我们可以看到分析器是怎么帮我们分词的。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

  1. {
  2. "number_of_clicks": {
  3. "type": "integer"
  4. }
  5. }

默认, string 类型域会被认为包含全文。就是说,它们的值在索引前,会通过 一个分析器,针对于这个域的查询在搜索前也会经过一个分析器。

  • index

index属性控制了怎样所以字符串,值可以为:

1、analyzed

首先分析字符串,然后索引它。换句话说,以全文索引这个域。

2、not_analyzed

索引这个域,所以可以搜索到它,但索引指定的精确值。不对它进行分析。

3、no

这个域不会被搜索到。

  1. {
  2. "tag": {
  3. "type": "string",
  4. "index": "not_analyzed"
  5. }
  6. }
  • analyzer

对于 analyzed 字符串域,用 analyzer 属性指定在搜索和索引时使用的分析器。默认, Elasticsearch 使用 standard 分析器, 但你可以指定一个内置的分析器替代它,例如 whitespace 、 simple 和 english:

  1. {
  2. "tweet": {
  3. "type": "string",
  4. "analyzer": "english"
  5. }
  6. }

更新映射

首次 创建一个索引的时候,可以指定类型的映射。你也可以使用 /_mapping 为新类型(或者为存在的类型更新映射)增加映射。

注意:尽管你可以增加一个已经存在的映射,但无法修改存在的域映射。如果一个域的映射已经存在,那么该域的数据可能已经被索引。如果你意图修改这个域的映射,索引的数据可能会出错,不能被正常的搜索。

  • 创建索引时指定映射
  1. PUT /gb
  2. {
  3. "mappings": {
  4. "tweet" : {
  5. "properties" : {
  6. "tweet" : {
  7. "type" : "string",
  8. "analyzer": "english"
  9. },
  10. "date" : {
  11. "type" : "date"
  12. },
  13. "name" : {
  14. "type" : "string"
  15. },
  16. "user_id" : {
  17. "type" : "long"
  18. }
  19. }
  20. }
  21. }
  22. }

这段代码指定了tweet类型的映射,把tweet属性使用english分析器,是一个全文string类型。date为日期类型,name为全文string类型使用standard分析器,user_id是长整型。

  • 新增一个属性,并指定映射
  1. PUT /gb/_mapping/tweet
  2. {
  3. "properties" : {
  4. "tag" : {
  5. "type" : "string",
  6. "index": "not_analyzed"
  7. }
  8. }
  9. }

新增了一个tag属性,为一个精确值string类型,即不对这个字段作分析

我们来测试一下

  1. GET /gb/_analyze?field=tweet&text=Black-cats
  2.  
  3. 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. Lyrics来源

    Lyre 里拉琴,古希腊语,在北欧流行至中世纪.   Lyrics in sheet music. This is a homorhythmic (i.e., hymn-style) arrangem ...

  2. Mysql 数据库日志与数据文件分开

    参考:https://blog.csdn.net/jiao_fuyou/article/details/78366621 myql默认配置情况下,二进制日志文件是保存在默认的数据目录 data 下,如 ...

  3. 【IDEA填坑】xml不编译

    今天在maven编译Springboot项目的时候,发现src/main/resources下的配置文件编译失败(就是war包中没有放入xml配置文件导致程序启动失败),经查询资料,发现新版本的IDE ...

  4. Project中最常用的注意点

    最近用Project 2013做计划,做工作量的评估,感觉确实牛逼得一塌糊涂.这几天自己试着做一些手工的计算,与Project的结果进行对比,发现学到的很多东西,网上确实很难道到,花了几天的时间研究, ...

  5. 基于C#简单实现多个word文件和Excel文件的全局字符串替换

    公司整理文档工作中,出现了一个需要使用全局字符替换多个word文档.excel文档中的内容的需求.虽然office.WPS都有全局替换的功能(ctrl+h),但是文件过多,且需要替换多次,工作量还是比 ...

  6. Nginx 作用

    django 请求的生命周期 Nginx 的作用: 浏览器 --- nginx(反向代理器)-- uwsgi --- django项目nginx : 负载均衡, 将任务分发给不同的uwsgi 动静分离 ...

  7. TCP三次握手的思考?

    大家都知道TCP有三次握手的过程,今天我就仔细想了想为什么TCP要有三次握手 先贴一张三次握手的示意图,说明一点是在三次握手中A是在第二次握手后申请缓存资源,B是在第一次握手后申请. 其实这个问题就是 ...

  8. Fortran程序调试中的“吐核”错误

    在CentOS7上安装了PGI编译器,但是调试过程中遇到的“段错误(吐核)”一直让人很头疼. 通常采用在程序中增加屏幕输出代码的方式来追踪和定位出错的变量,比如下面这个样例程序就在第16行和第18行增 ...

  9. 运用python发邮件

    1.网上有许多发送邮件的代码,运行了几次都不成功(使用python3),转用Python2之后,发送成功 2.代码样例: 参考教程:http://www.runoob.com/python/pytho ...

  10. Spring Websocket实现简易在线聊天功能

    针对Spring Websocket的实现,我参照了其他博主的文章https://www.cnblogs.com/leechenxiang/p/5306372.html 下面直接给出实现: 一.引入相 ...