Elasticsearch笔记3 基础入门

映射和分析

精确值VS全文

  • 精确值查询: 判断值与检索条件是匹配还是不匹配的关系。
  • 全文: 判断值与检索条件是否匹配,匹配度是多少的关系。

倒排索引

一个倒排索引由文档中所有的不重复词的列表构成,对于其中每个词,有一个包含他的文档。

词条文档1文档2文档3
北京101
上海111
广州001
重庆011

实例搜索北京,文档1和文档2将被返回。

分析与分析器

分析过程

  • 首先,将文档分成适合与倒排索引的独立词条。
  • 之后,将这些词条按照标准规则进行转化,用于提高检索率。

分词器的功能

  • 字符过滤器
    • 不同的字符过滤器规则不同,比如去除各种符号。
  • 分词器
    • 不同的分词器拆分规则不同,比如遇到空格就拆分。
  • token过滤器
    • 不同的token过滤器规则不同,比如统一小写化,近义词转换等等。

ES支持自定义分词器

内置分词器

  • 标准分词器
  • 简单分词器
  • 空格分词器
  • 语言分析器

分词器的使用点

  • 进行全文检索时,先经过分词器对条件做标准处理。
  • 进行精确值检索时,不会进行分词器标准处理。

测试分词器

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

指定分词器

在建立映射的时候。

映射

映射不可更改,可以任意增加。

核心简单类型

  • 字符串 string
  • 整数 byte,short,integer,long
  • 浮点型 folat,double
  • 布尔型 true,false
  • 日期 date

动态映射

当未创建映射时,ES会根据值格式推断类型。

查看映射

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

自定义索引

  • 全文字符串域和精确值字符串域的区别
  • 使用特定语言分析器
  • 优化域以适应部分匹配
  • 指定自定义数据格式
  • 还有更多

暂时不用 略

测试映射

GET /gb/_mapping/tweet

以下内容带规整

复杂核心类型

JSON.NULL,对象,数组

多值域(数组)

数组内元素类型要求一致

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

空域(NULL)

空域不能被索引

多层级对象(嵌套Object)

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

内部管理方式

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

文档中35岁的Mary对象,被索引年龄和索引姓名分别记录,破坏了相关性

请求体查询

GET请求带BODY体,可能被一些服务器拒绝。可以把GET改成POST,效果一样。

空查询

GET /_search
{} 

查询表达式

GET /_search
{
    "query": YOUR_QUERY_HERE
}

查询语句的结构

{
    QUERY_NAME: {
        ARGUMENT: VALUE,
        ARGUMENT: VALUE,...
    }
}

实例

GET /_search
{
    "query": {
        "match": {
            "tweet": "elasticsearch"
        }
    }
}

合并查询语句的结构

查询语句就像一些简单的组合块,这些组合块可以彼此之间合并组成更复杂的查询。

  • 叶子语句 被执行的检索条件
  • 复合语句 用于关联各检索条件之间关系的部分
    • must 匹配
    • must_not 不匹配
    • should 或者匹配
    • filters 不评分过滤器
{
    "bool": {
        "must":     { "match": { "tweet": "elasticsearch" }},
        "must_not": { "match": { "name":  "mary" }},
        "should":   { "match": { "tweet": "full text" }},
        "filter":   { "range": { "age" : { "gt" : 30 }} }
    }
}
{
    "bool": {
        "must": { "match":   { "email": "business opportunity" }},
        "should": [
            { "match":       { "starred": true }},
            { "bool": {
                "must":      { "match": { "folder": "inbox" }},
                "must_not":  { "match": { "spam": true }}
            }}
        ],
        "minimum_should_match": 1
    }
}

查询与过滤

Elasticsearch 使用的查询语言(DSL)拥有一套查询组件,这些组件可以以无限组合的方式进行搭配。这套组件可以在以下两种情况下使用:过滤情况(filtering context)和查询情况(query context)。

  • 当DSL用于过滤情况时,查询被设置成一个“不评分”或者“过滤”的查询。
    这个查询只是简单的问是否匹配,结果得到是或者否
  • 当DSL用于查询情况时,查询呗设置成一个“评分”的查询。
    这个查询不只是简单的问是否匹配,还要计算匹配度。

性能

不评分查询性能高于评分查询

最重要的查询(查询单元)

  • match_all
    匹配所有
  • match
    是否匹配,支持精准和全文查询。
  • multi_match
    一种match的简写,可以将同一条件指定给多个字段
  • range
    范围匹配,支持数字和时间类型。gt 大于 gte 大于等于 lt小于 lte 小于等于
  • term
    是否匹配,仅用于精准匹配。
  • terms
    一种merm的简写,可以将同一条件指定给多个字段
  • exists和missing
    查询被用于查找那些指定字段中有值 (exists) 或无值 (missing) 的文档

组合多查询(组合查询单元)

将查询单元按规则组装

  • must
    文档 必须 匹配这些条件才能被包含进来。
  • must_not
    文档 必须 匹配这些条件才能被包含进来。
  • should
    如果满足这些语句中的任意语句,将增加 _score ,否则,无任何影响。它们主要用于修正每个文档的相关性得分。
  • filters
    必须 匹配,但它以不评分、过滤模式来进行。这些语句对评分没有贡献,只是根据过滤标准来排除或包含文档。

各种复杂组合格式参考示例

{
    "bool": {
        "must":     { "match": { "title": "how to make millions" }},
        "must_not": { "match": { "tag":   "spam" }},
        "should": [
            { "match": { "tag": "starred" }},
            { "range": { "date": { "gte": "2014-01-01" }}}
        ]
    }
}
{
    "bool": {
        "must":     { "match": { "title": "how to make millions" }},
        "must_not": { "match": { "tag":   "spam" }},
        "should": [
            { "match": { "tag": "starred" }}
        ],
        "filter": {
          "range": { "date": { "gte": "2014-01-01" }} 
        }
    }
}
{
    "bool": {
        "must":     { "match": { "title": "how to make millions" }},
        "must_not": { "match": { "tag":   "spam" }},
        "should": [
            { "match": { "tag": "starred" }}
        ],
        "filter": {
          "bool": { 
              "must": [
                  { "range": { "date": { "gte": "2014-01-01" }}},
                  { "range": { "price": { "lte": 29.99 }}}
              ],
              "must_not": [
                  { "term": { "category": "ebooks" }}
              ]
          }
        }
    }
}

constant_score

只有过滤的查询语句格式

{
    "constant_score":   {
        "filter": {
            "term": { "category": "ebooks" } 
        }
    }
}

验证查询

验证查询语句是否合法

GET /gb/tweet/_validate/query
{
   "query": {
      "tweet" : {
         "match" : "really powerful"
      }
   }
}

理解错误信息

添加?explain参数,显示错误信息

GET /gb/tweet/_validate/query?explain 
{
   "query": {
      "tweet" : {
         "match" : "really powerful"
      }
   }
}
{
  "valid" :     false,
  "_shards" :   { ... },
  "explanations" : [ {
    "index" :   "gb",
    "valid" :   false,
    "error" :   "org.elasticsearch.index.query.QueryParsingException:
                 [gb] No query registered for [tweet]"
  } ]
}

解读查询语句

添加?explain参数,显示错误信息

GET /gb/tweet/_validate/query?explain 
{
   "query": {
      "tweet" : {
         "match" : "really powerful"
      }
   }
}
{
  "valid" :         true,
  "_shards" :       { ... },
  "explanations" : [ {
    "index" :       "us",
    "valid" :       true,
    "explanation" : "tweet:really tweet:powerful"
  }, {
    "index" :       "gb",
    "valid" :       true,
    "explanation" : "tweet:realli tweet:power"
  } ]
}

排序与相关性

默认排序

默认情况下ES采用相关性降序排序,相关性采用浮点型记录,通过_sorce字段展示。
当指定特定字段进行排序,则_sorce为空,并且不会进行相关性计算(算了没有用处)。

多级排序

GET /_search
{
    "query" : {
        "bool" : {
            "must":   { "match": { "tweet": "manage text search" }},
            "filter" : { "term" : { "user_id" : 2 }}
        }
    },
    "sort": [
        { "date":   { "order": "desc" }},
        { "_score": { "order": "desc" }}
    ]
}

多值字段排序

先根据指定的排序模式对数组内部进行排序,在用结果值参与整体排序。
数字或时间类型的多值字段,可选以下模式进行内部排序

  • min(默认)
  • max
  • avg
  • sum
  • 等等
"sort": {
    "dates": {
        "order": "asc",
        "mode":  "min"
    }
}

一个字段配置多种索引类型(虚拟字段)

当字符串类型采用全文索引的情况下,不能再进行精准查询,通过配置虚拟字段来解决。
虚拟字段不会存两份原数据,而是存两份索引结果。
所有的 _core_field 类型 (strings, numbers, Booleans, dates) 接收一个 fields 参数,该参数允许你转化一个简单的映射如:
原始

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

虚拟字段

"tweet": { 
    "type":     "string",
    "analyzer": "english",
    "fields": {
        "raw": { 
            "type":  "string",
            "index": "not_analyzed"
        }
    }
}

此时支持tweet全文检索,也支持tweet.raw精准查询

相关性

词频(DF)

定义:一词语出现的次数除以总词语数。
实例
假设一篇文档总共100个词语,JAVA词语出现了10次。则频率=10%(10/100)

文档频率

定义:包含一词语的文件数除以文件总数
实例
假设共有10000份分档,包含JAVA词语的有100份。则文件频率=1%(100/10000)

逆文档频率(反向文档频率)(IDF)

定义:词频/文件频率
实例
逆文档频率=10(0.1/0.01)

字段长度准则

假设一个词语长度为2,出现在一个长度100的长语句中。
假设一个词语长度为2,出现在一个长度10的段语句中。
则认为 第二项的准确度比第一项的高

理解评分标准

通过添加explain参数,在返回的每个文档后追加评分依据信息。

GET /_search?explain 
{
   "query"   : { "match" : { "tweet" : "honeymoon" }}
}

正常内容

{
    "_index" :      "us",
    "_type" :       "tweet",
    "_id" :         "12",
    "_score" :      0.076713204,
    "_source" :     { ... trimmed ... },

展示文档来源,节点和分片。词频率和文档频率是在分片中计算的。

"_shard" :      1,
"_node" :       "mzIVYCsqSWCG_M_ZffSs9Q",

_explanation部分展示了所有细节。
例如相关性评分总结,检索词频率,反向文档频率,字段长度频率等

"_explanation": { 
   "description": "weight(tweet:honeymoon in 0)
                  [PerFieldSimilarity], result of:",
   "value":       0.076713204,
   "details": [
      {
         "description": "fieldWeight in 0, product of:",
         "value":       0.076713204,
         "details": [
            {  
               "description": "tf(freq=1.0), with freq of:",
               "value":       1,
               "details": [
                  {
                     "description": "termFreq=1.0",
                     "value":       1
                  }
               ]
            },
            { 
               "description": "idf(docFreq=1, maxDocs=1)",
               "value":       0.30685282
            },
            { 
               "description": "fieldNorm(doc=0)",
               "value":        0.25,
            }
         ]
      }
   ]
}

理解某文档是如何匹配到的,或者如何被排除掉的

GET /us/tweet/12/_explain
{
   "query" : {
      "bool" : {
         "filter" : { "term" :  { "user_id" : 2           }},
         "must" :  { "match" : { "tweet" :   "honeymoon" }}
      }
   }
}

Doc values

Doc Values 是在索引时与 倒排索引 同时生成。
Doc Values 和 倒排索引 都是经过分词器处理后保存的,所以不可变更。

倒排索引结构

词条文档1文档2文档3
北京101
上海111
广州001
重庆011

Doc Values结构

文档词条
文档1北京,上海
文档2上海,重庆
文档3北京,上海,广州,重庆

Doc Values的持久化与压缩

Doc Values保存在磁盘上,并且是压缩保存的。因为cpu性能远高于磁盘。

Doc Values应用场景

  • 对一个字段进行排序
  • 对一个字段进行聚合
  • 某些过滤,比如地理位置过滤
  • 某些与字段相关的脚本计算

举例

假设计算两个文档的交集,不适合用倒排索引计算,而Doc Values更适合。

文章中部分内容来源于:
Elasticsearch: The Definitive Guide by Clinton Gormley and Zachary Tong (O’Reilly). Copyright 2015 Elasticsearch BV, 978-1-449-35854-9。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值