ElasticSearch【有与无】【搜索引擎】【ES6】映射和分析

目录

 

1.简介

1.1.数据类型的差异,导致查询结果不同

1.2.确切值(Exact values) 对决全文(Full text)

1.3.倒序索引(inverted index)

1.4.分析(analysis)

① 字符过滤器(character filter)

② 分词器(tokenizer)

③ 标记过滤

内建的分析器

1.5.映射

查看映射

自定义字段映射

更新映射

测试映射

1.6.复合核心字段类型

多值字段

空字段

多层对象

内部对象的映射

内部对象是怎样被索引的

对象-数组


1.简介

映射(mapping)机制

    用于进行字段类型确认,将每个字段匹配为一种确定的数据类型( string  ,  number  ,  booleans  ,  date  等)。

分析(analysis)机制

    用于进行全文文本(Full Text)的分词,以建立供搜索用的反向索引。_all  因为是默认字段是 string  类型。

 

1.1.数据类型的差异,导致查询结果不同

Elasticsearch为对字段类型进行猜测,动态生成了字段和类型的映射关系。

date  类型的字段和 string  类型的字段的索引方式是不同的。

Elasticsearch中,每一种核心数据类型(strings, numbers, booleans及dates)以不同的方式进行索引。

确切值(exact values)全文文本(full text)

这是区分搜索引擎和其他数据库的根本差异。

 

1.2.确切值(Exact values) 对决全文(Full text)

确切值是确定的

全文文本,常常被称为 非结构化数据  ,其实是一种用词不当的称谓,实际上自然语言是高度结构化的。

为了方便在全文文本字段中进行这些类型的查询,Elasticsearch首先对文本分析(analyzes),然后使用结果建立一个倒排索引。

 

1.3.倒序索引(inverted index)

快速的全文搜索

倒排索引:由在文档中出现的唯一的单词列表,以及对于每个单词在文档中的位置组成。

标记化和标准化的过程叫做分词(analysis)

 

1.4.分析(analysis)

【分析器(analyzer)工作过程】

  1. 标记化一个文本块为适用于倒排索引单独的词(term)
  2. 标准化这些词为标准形式,提高它们的“可搜索性”或“查全率”

【包装】

① 字符过滤器(character filter)

① 字符串经过字符过滤器(character filter),它们的工作是在标记化前处理字符串。

      字符过滤器能够去除HTML标记,或者转换 "&"  为 "and"  。

② 分词器(tokenizer)

分词器(tokenizer)被标记化成独立的词。

一个简单的分词器(tokenizer)可以根据空格或逗号将单词分开(这个在中文中不适用)。

③ 标记过滤

每个词都通过所有标记过滤(token filters),它可以修改词,或者增加词。

内建的分析器

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

 

标准分析器

Elasticsearch默认使用的分析器

对于文本分析,它对于任何语言都是最佳选择。它根据Unicode Consortium的定义的单词边界(word boundaries)来切分文本,然后去掉大部分标点符号。最后,把所有词转为小写。

set, the, shape, to, semi, transparent, by, calling, set_trans, 5

 

简单分析器

简单分析器将非单个字母的文本切分,然后把每个词转为小写

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

 

空格分析器

空格分析器依据空格切分文本。它不转换小写。

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

 

语言分析器

特定语言分析器适用于很多语言。能够考虑到特定语言的特性。

english  分析器将会产生以下结果:
set, shape, semi, transpar, call, set_tran, 5

 

当分析器被使用

GET /_search?q=2014                         # 2014 是字符串

GET /_search?q=2014-09-15               # 2014-09-15 是字符串

GET /_search?q=date:2014-09-15       # 2014-09-15 是日期

GET /_search?q=date:2014                  # 2014 是日期

 

测试分析器

GET /_analyze?analyzer=standard&text=Text to analyze

【结果】

{
    "tokens": [
    {
        "token": "text",           // 一个实际被存储在索引中的词
        "start_offset": 0,        // 表示词在原文本中占据的位置
        "end_offset": 4,         // 表示词在原文本中占据的位置
        "type": "<ALPHANUM>",
        "position": 1              // 指明词在原文本中是第几个出现的
    },
    {
        "token": "to",
        "start_offset": 5,
        "end_offset": 7,
        "type": "<ALPHANUM>",
        "position": 2
    },
    {
        "token": "analyze",
        "start_offset": 8,
        "end_offset": 15,
        "type": "<ALPHANUM>",
        "position": 3
    }]
}

 

指定分析器

当Elasticsearch在你的文档中探测到一个新的字符串字段,它将自动设置它为全文 string  字段并用 standard  分析器分析。

 

1.5.映射

核心简单字段类型
类型表示的数据类型
Stringstring
Whole numberbyte  ,  short  ,  integer  ,  long
Floating point float  ,  double
Booleanboolean
Datedate

 

 

 

 

 

 

动态映射猜测字段类型,JSON的基本数据类型
JSON typeField type
Boolean:  true  or  false"boolean"
Whole number:  123"long"
Floating point:  123.45"double"
String, valid date:  "2014-09-15""date"
String:  "foo bar""string"

 

 

 

 

 

 

注意
如果索引一个带引号的数字—— "123",它将被映射为 "string"  类型,而不是 "long" 类型。
如果字段已经被映射为 "long" 类型,Elasticsearch将尝试转换字符串为long,并在转换失败时会抛出异常。

查看映射

映射(叫做属性(properties))是Elasticsearch在创建索引时动态生成。

【举例】

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"
                   }
                }
           }
        }
    }
}

小提示
错误的映射,例如把 age 字段映射为 string 类型而不是 integer 类型,会造成查询结果混乱。
要检查映射类型,而不是假设它是正确的!

自定义字段映射

自定义类型可以使你完成以下几点:

  • 区分全文(full text)字符串字段和准确字符串字段
  • 使用特定语言的分析器
  • 优化部分匹配字段
  • 指定自定义日期格式
  • 以及更多

映射中最重要的字段参数是 type  。除了 string 类型的字段,可能很少需要映射其他的 type。

{
    "number_of_clicks": {
        "type": "integer"
    }
}

string  类型的字段,默认的,考虑到包含全文本,它们的值在索引前要经过分析器分析,并
且在全文搜索此字段前要把查询语句做分析处理。

对于 string  字段,两个最重要的映射参数是 index  和 analyer  。

 

index

index  参数控制字符串以何种方式被索引。

解释
analyzed首先分析这个字符串,然后索引。换言之,以全文形式索引此字段。
not_analyzed索引这个字段,使之可以被搜索,但是索引内容和指定值一样。不分析此字段。
no不索引这个字段。这个字段不能为搜索到。

 

 

 

 

 

string  类型字段默认值是 analyzed  。如果想映射字段为确切值,需要设置它为 not_analyzed  :

{
    "tag": {
        "type": "string",
        "index": "not_analyzed"
    }
}

其他简单类型(long 、 double 、 date 等等)也接受 index 参数,但相应的值只能是 no 和 not_analyzed,它们的值不能被分析。

分析

对于 analyzed  类型的字符串字段,使用 analyzer  参数来指定哪一种分析器将在搜索和索引的时候使用。

默认使用 standard 分析器,但是可以通过指定一个内建的分析器来更改它,例如 whitespace 、 simple 或 english。

{
    "tweet": {
        "type": "string",
        "analyzer": "english"
    }
}

更新映射

可以在第一次创建索引的时候指定映射的类型。

也可以晚些时候为新类型添加映射(或者为已有的类型更新映射)。

重要
可以向已有映射中增加字段,但不能修改它。
如果一个字段在映射中已经存在,这可能意味着那个字段的数据已经被索引。
如果改变了字段映射,那已经被索引的数据将错误并且不能被正确的搜索到。

可以更新一个映射来增加一个新字段,但是不能把已有字段的类型那个从 analyzed  改到 not_analyzed  。

【举例】

①  删除索引 gb

  DELETE /gb

②  创建一个新索引,指定 tweet  字段的分析器为 english 

  PUT /gb          // 将创建包含 mappings 的索引,映射在请求体中指定
  {
  "mappings": {
    "tweet" : {
      "properties" : {
        "tweet" : {
          "type" : "string",
          "analyzer": "english"
        },
        "date" : {
          "type" : "date"
        },
        "name" : {
          "type" : "string"
        },
        "user_id" : {
          "type" : "long"
        }
      }
    }
  }
}

在 tweet  的映射中增加一个新的 not_analyzed  类型的文本字段,叫做 tag  ,使用 _mapping  后

PUT /gb/_mapping/tweet
{
    "properties" : {
        "tag" : {
            "type" : "string",
            "index": "not_analyzed"
        }
    }
}

合并至存在的那个映射

 

测试映射

通过名字使用 analyze  API测试字符串字段的映射

GET /gb/_analyze?field=tweet&text=Black-cats

GET /gb/_analyze?field=tag&text=Black-cats

 

1.6.复合核心字段类型

多值字段

{ "tag": [ "search", "nosql" ]}

对于数组不需要特殊的映射。任何一个字段可以包含零个、一个或多个值,同样对于全文字段将被分析并产生多个词。

数组中所有值必须为同一类型。不能把日期和字符窜混合。

当从Elasticsearch中取回一个文档,任何一个数组的顺序和索引它们的顺序一致。
取回的 _source 字段的顺序同样与索引的顺序相同。
然而,数组是做为多值字段被索引的,没有顺序。在搜索阶段不能指定“第一个值”或者“最后一个值”。

空字段

当然数组可以是空的。这等价于有零个值。事实上,Lucene没法存放 null  值,所以一个 null  值的字段被认为是空字段。

这四个字段将被识别为空字段而不被索引:

"empty_string": "",
"null_value": null,
"empty_array": [],
"array_with_null_value": [ null ]

 

多层对象

自然JSON数据类型是对象(object)

内部对象(inner objects)经常用于在另一个对象中嵌入一个实体或对象。

{
    "tweet": "Elasticsearch is very flexible",
    "user": {
        "id": "@johnsmith",
        "gender": "male",
        "age": 26,
        "name": {
            "full": "John Smith",
            "first": "John",
            "last": "Smith"
        }
    }
}

内部对象的映射

{
    "gb": {
        "tweet": {     // 根对象
            "properties": {
                "tweet": { "type": "string" },
                "user": {   // 内部对象
                    "type": "object",
                    "properties": {
                        "id": { "type": "string" },
                        "gender": { "type": "string" },
                        "age": { "type": "long" },
                        "name": {   // 内部对象
                            "type": "object",
                            "properties": {
                                "full": { "type": "string" },
                                "first": { "type": "string" },
                                "last": { "type": "string" }
                            }
                        }
                    }
                }
            }
        }
    }
}

内部对象是怎样被索引的

Lucene 并不了解内部对象。 一个 Lucene 文件包含一个键-值对应的扁平表单。

【文件格式(扁平化)】

{
    "tweet": [elasticsearch, flexible, very],
    "user.id": [@johnsmith],
    "user.gender": [male],
    "user.age": [26],
    "user.name.full": [john, smith],
    "user.name.first": [john],
    "user.name.last": [smith]
}

对象-数组

一个包含内部对象的数组如何索引?

{
   "followers": [
      { "age": 35, "name": "Mary White"},
      { "age": 26, "name": "Alex Jones"},
      { "age": 19, "name": "Lisa Smith"}
   ]
}

扁平化后

{
    "followers.age": [19, 26, 35],
    "followers.name": [alex, jones, lisa, smith, mary, white]
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

琴 韵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值