zoukankan      html  css  js  c++  java
  • Elasticsearch检索分类详解

    前言

    Elasticsearch中当我们设置Mapping(分词器、字段类型)完毕后,就可以按照设定的方式导入数据。

    有了数据后,我们就需要对数据进行检索操作。根据实际开发需要,往往我们需要支持包含但不限于以下类型的检索: 
    1)精确匹配,类似mysql中的 “=”操作; 
    2)模糊匹配,类似mysql中的”like %关键词% “查询操作; 
    3)前缀匹配; 
    4)通配符匹配; 
    5)正则表达式匹配; 
    6)跨索引匹配; 
    7)提升精读匹配。

    细数一下,我们的痛点在于: 
    1)ES究竟支持哪些检索操作? 
    2)如何实现ES精确值检索、指定索引检索、全文检索?

    这些就是本文着重参考ES最新官方文档,针对ES5.X版本探讨的内容。

    0、检索概览

    检索子句的行为取决于查询应用于过滤(filter)上下文还是查询/分析(query)上下文。

    过滤上下文——对应于结构化检索

    1)核心回答的问题是:“这个文档是否符合这个查询条款?” 
    
    2)答案是简单的是或否,不计算分数。 
    
    3)过滤器上下文主要用于过滤结构化数据。类似于Mysql中判定某个字段是否存在: 

    例如: 

    a. 时间戳字段:是否属于2015年或2016年? 
    b. 状态字段:是否设置为“已发布”?

    经常使用的过滤器将被Elasticsearch**自动缓存,以加快性能**。

    分析上下文——对应于全文检索 
    1)核心回答了“本文档与此查询子句是否匹配?”的问题。

    2)除了决定文档是否匹配之外,查询子句还会计算一个_score,表示文档与其他文档的匹配程度。

    综合应用场景如下:

    GET /_search
    {  "query": {  "bool": {  "must": [
      { "match": { "title": "Search" }},
      { "match": { "content": "Elasticsearch" }}
      ],  "filter": [
      { "term": { "status": "published" }},
      { "range": { "publish_date": { "gte": "2015-01-01" }}}
      ]
      }
      }
    }

    以上检索,title中包含”Search”并且content中包含 “Elasticsearch”,status中精确匹配”published”,并且publish_date 大于“2015-01-01”的全部信息。以下,以“脑图”的形式直观展示检索分类:

    以下内容的原文需要参考ES官方文档(随着版本变化,后续会有更新)

    1、结构化检索

    针对字段类型: 日期、时间、数字类型,以及精确的文本匹配。 
    结构化检索特点: 
    * 1)结构化查询,我们得到的结果 总是 非是即否,要么存于集合之中,要么存在集合之外。 
    * 2)结构化查询不关心文件的相关度或评分;它简单的对文档包括或排除处理。

    1.1 精确值查找

    1.1.1 单个精确值查找(term query)

    term 查询会查找我们指定的精确值。term 查询是简单的,它接受一个字段名以及我们希望查找的数值。

    想要类似mysql中如下sql语句的查询操作:

    SELECT document FROM products WHERE price = 20; 
    DSL写法:

    GET /my_store/products/_search
    {
      "query" : {
      "term" : {
      "price" : 20
      }
      }
    }

    当进行精确值查找时, 我们会使用过滤器(filters)。过滤器很重要,因为它们执行速度非常快,不会计算相关度(直接跳过了整个评分阶段)而且很容易被缓存。如下: 使用 constant_score 查询以非评分模式来执行 term 查询并以一作为统一评分。

    GET /my_store/products/_search
    {
      "query" : {
      "constant_score" : {
      "filter" : {
      "term" : {
      "price" : 20
      }
      }
      }
      }
    }

    注意:5.xES中,对于字符串类型,要进行精确值匹配。需要讲类型设置为text和keyword两种类型。mapping设置如下:

    POST testindex/testtype/_mapping
    {
       "testtype ":{
      "properties":{
      "title":{
      "type":"text",
      "analyzer":"ik_max_word",
      "search_analyzer":"ik_max_word",
      "fields":{
      "keyword":{
      "type":"keyword"
      }
      }
      }
    }
    }

    1.1.2 布尔过滤器

    一个 bool 过滤器由三部分组成:

    {
       "bool" : {
          "must" :     [],
          "should" :   [],
          "must_not" : [],
          "filter":    []
       }
    }

    must ——所有的语句都 必须(must) 匹配,与 AND 等价。 

    must_not ——所有的语句都 不能(must not) 匹配,与 NOT 等价。 
    should ——至少有一个语句要匹配,与 OR 等价。 
    filter——必须匹配,运行在非评分&过滤模式。 
    就这么简单! 当我们需要多个过滤器时,只须将它们置入 bool 过滤器的不同部分即可。

    举例:

    GET /my_store/products/_search
    {
      "query" : {
      "filtered" : {
      "filter" : {
      "bool" : {
      "should" : [
      { "term" : {"price" : 20}},
      { "term" : {"productID" : "XHDK-A-1293-#fJ3"}}
      ],
      "must_not" : {
      "term" : {"price" : 30}
      }
      }
      }
      }
      }
    }

    1.1.3 多个值精确查找(terms query)

    {
      "terms" : {
      "price" : [20, 30]
      }
    }

    如上,terms是包含的意思,包含20或者包含30。 
    如下实现严格意义的精确值检索, tag_count代表必须匹配的次数为1。

    GET /my_index/my_type/_search
    {
      "query": {
      "constant_score" : {
      "filter" : {
      "bool" : {
      "must" : [
      { "term" : { "tags" : "search" } },
      { "term" : { "tag_count" : 1 } }
      ]
      }
      }
      }
      }
    }

    1.2 范围检索(range query)

    range 查询可同时提供包含(inclusive)和不包含(exclusive)这两种范围表达式,可供组合的选项如下:

    gt: > 大于(greater than)
    lt: < 小于(less than)
    gte: >= 大于或等于(greater than or equal to)
    lte: <= 小于或等于(less than or equal to)

    类似Mysql中的范围查询:

    SELECT document
    FROM   products
    WHERE  price BETWEEN 20 AND 40

    ES中对应的DSL如下:

    GET /my_store/products/_search
    {
      "query" : {
      "constant_score" : {
      "filter" : {
      "range" : {
      "price" : {
      "gte" : 20,
      "lt" : 40
      }
      }
      }
      }
      }
    }

    1.3 存在与否检索(exist query)

    mysql中,有如下sql: 
    SELECT tags FROM posts WHERE tags IS NOT NULL;

    ES中,exist查询某个字段是否存在:

    GET /my_index/posts/_search
    {
        "query" : {
            "constant_score" : {
                "filter" : {
                    "exists" : { "field" : "tags" }
                }
            }
        }
    }

    https://blog.csdn.net/laoyang360/article/details/77623013   1.3接着往下面开始

  • 相关阅读:
    坐标系统和投影的来龙去脉原创
    ArcEngine这本书怎么样
    如何构建达芬奇的DSP Server【转】
    ccs编译问题
    linux下环境变量设置[转]
    普通人的编辑利器——Vim 【转】
    关闭linux防火墙
    GT_Trace的使用[z]
    davinciDM6446 LINUX环境配置
    TI DaVinci(达芬奇)入门
  • 原文地址:https://www.cnblogs.com/pyspark/p/8817704.html
Copyright © 2011-2022 走看看