Elasticsearch:理解 Percolator 数据类型及 Percolate 查询

本文涉及的产品
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
简介: Elasticsearch 是一款功能强大且功能丰富的搜索工具。本文将介绍一种小众的数据类型 Percolator ,同时介绍Percolate query的使用。 您需要基本了解 Elasticsearch,尤其是mapping和search。
作者
刘晓国,Elastic 公司社区布道师。新加坡国立大学硕士,西北工业大学硕士,曾就职于新加坡科技,康柏电脑,通用汽车,爱立信,诺基亚,Linaro,Ubuntu,Vantiq 等企业。

编辑
丛聿,架构师(搜索方向)

前言

Elasticsearch 是一款功能强大且功能丰富的搜索工具。本文将介绍一种小众的数据类型 Percolator ,同时介绍Percolate query的使用。 您需要基本了解 Elasticsearch,尤其是mapping和search。

概念

Elasticsearch 的正常工作流程是将文档(JSON数据)存储在索引中,然后在执行搜索时通过索引查询这些文档的信息。设想如果反转这种使用流程将如何(即先有查询条件,再有文档),Percolate即可实现这种逆转的流程。其使用流程是先存储search条件,之后使用文档询问是否可命中这些搜索条件。本文接下来将介绍如何构造和使用percolator。

Percolation功能围绕percolator字段类型展开。 与其他字段类型一样(先在mappings中定义,再进行写入),不同的是它将搜索条件作为文档进行存储。当存储数据时,索引会将此搜索条件的文档处理为可执行形式,并将其保存以备后用。

Percolate query接受一个或多个文档,并返回预先存储的搜索条件文档(该条件至少匹配一个传入的文档)。在执行搜索时,Percolate query的工作原理与其他任何查询模式一样,不同的一些细节将在下文介绍。

深入理解

在底层,具有percolate字段的索引将保留于一个隐藏的索引(内存中)。查询时,首先将在 percolate query 中列出的文档放入该索引,然后对该索引执行常规查询,看与原始的含 percolate 字段的搜索条件是否匹配。

该隐藏索引是从原始 percolator 索引获取其映射的。因此,用于 percolate query 的索引字段需要具有适合原始数据和查询文档数据的mappings配置。

这引入了一些索引管理的问题,因为你的索引数据和 percolate query 文档可能以不同的方式使用同一字段。一个简单的方式是使用对象类型(object type) 将 percolate 相关的映射与普通文档映射分开,具体可参考后文给出的例子。

假设你使用的查询最初是为另一个索引A中的数据编写的,那么最直接的方法是将数据隔离以避免数据直接写到 percolate 索引中去,并将索引A中根级别的mappings在 percolate索引中进行定义。

此外,由于percolate field被解析为搜索条件并在索引时保存,因此在升级ES主版本后可能需要reindex Percolate文档。

示例

在此示例中,我们将建立一个索引,该索引含有保存的玩具名字和玩具价格搜索条件。其背后思路是,用户输入搜索词和最高价格,然后在与该玩具名匹配的商品价格低于用户指定价格时立即得到通知。此外用户还可以打开和关闭这些通知。下面的映射通过percolate索引来支持此功能。与保存的搜索条件本身相关的字段位于search对象中,而与原始玩具相关的字段位于映射的根级别。

首先,我们使用如下命令来创建一个索引:

 PUT toys {
  "mappings": {
    "properties": {
      "search": {
        "properties": {
          "query": {
            "type": "percolator"
          },
          "user_id": {
            "type": "integer"
          },
          "enabled": {
            "type": "boolean"
          }
        }
      },
      "price": {
        "type": "float"
      },
      "description": {
        "type": "text"
      }
    }
  }
}

我们接着使用命令写入一个文档,即用户的查询条件。此处我们将数据存储在 search 对象字段中。price 和 description 的映射仅用于支持 percolate query。

PUT toys/_doc/1
{
  "search": {
    "user_id": 5,
    "enabled": true,
    "query": {
      "bool": {
        "filter": [
          {
           "match": {
              "description": {
                "query": "nintendo switch"
              }
            }
          },
          {
            "range": {
              "price": {
                "lte": 300
              }
            }
          }
        ] 
      }
    }
  }
}

查询时,我们要同时使用普通对象字段和“特殊的” percolator 字段。 此查询将在用户搜索时检查是否有当前启用的搜索条件与文档匹配。

GET toys/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "percolate": {
            "field": "search.query",
            "document": {
              "description": "Nintendo Switch",
              "price": 250
            }
          }
        },
        {
          "term": {
            "search.enabled": true
          }
        },
        {
          "term": {
            "search.user_id": 5
          }
        }
      ]
    }
  }
}

请注意,此处结合使用了基础字段的查询(search.user_id和search.enabled字段),以及percolator条件字段的查询(search.query),用以对指定的用户ID在启用状态下生效。

运行上面的指令后,我们可以看到如下结果:

 {
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 0.0,
    "hits" : [
      {
        "_index" : "toys",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 0.0,
        "_source" : {
          "search" : {
            "user_id" : 5,
            "enabled" : true,
           "query" : {
              "bool" : {
                "filter" : [
                  {
                    "match" : {
                      "description" : {
                        "query" : "nintendo switch"
                      }
                    }
                  },
                  {
                    "range" : {
                      "price" : {
                        "lte" : 300
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "fields" : {
          "_percolator_document_slot" : [
            0
          ] 
        }
      }
    ] 
  }
}

如果我们改用如下搜索条件

GET toys/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "percolate": {
            "field": "search.query",
            "document": {
              "description": "Nintendo Switch",
              "price": 500
            }
          }
        },
        {
          "term": {
            "search.enabled": true
          }
        },
        {
          "term": {
            "search.user_id": 5
          }
        }
      ] 
    }
  }
} 

其中price不满足percolate预先存储的条件,因此将找不到任何结果:

{
  "took" : 1, 
  "timed_out" : false, 
  "_shards" : {
    "total" : 1, 
    "successful" : 1, 
    "skipped" : 0, 
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 0, 
      "relation" : "eq"
    },
    "max_score" : null, 
    "hits" : [ ]
  }
}

结束语

在实际使用中,我们可以在 Logstash的Elasticsearch过滤器中 针对每个事件来使用 Elasticsearch 做 query。即我们也可以得到这个事件是否满足预设的 search条件,如果满足条件则可以执行其后续流程。

参考
【1】https://www.elastic.co/blog/elasticsearch-data-enrichment-with-logstash-a-few-security-examples

声明
本文由作者刘晓国授权转载,版权归作者所有,未经许可不得擅自转载或引用。

image.png

阿里云Elastic Stack】100%兼容开源ES,独有9大能力,提供免费 X-pack服务(单节点价值$6000)

相关活动


更多折扣活动,请访问阿里云 Elasticsearch 官网

阿里云 Elasticsearch 商业通用版,1核2G ,SSD 20G首月免费
阿里云 Logstash 2核4G首月免费
下载白皮书:Elasticsearch 八大经典场景应用


image.png

image.png

相关实践学习
使用阿里云Elasticsearch体验信息检索加速
通过创建登录阿里云Elasticsearch集群,使用DataWorks将MySQL数据同步至Elasticsearch,体验多条件检索效果,简单展示数据同步和信息检索加速的过程和操作。
ElasticSearch 入门精讲
ElasticSearch是一个开源的、基于Lucene的、分布式、高扩展、高实时的搜索与数据分析引擎。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr(也是基于Lucene)。 ElasticSearch的实现原理主要分为以下几个步骤: 用户将数据提交到Elastic Search 数据库中 通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据 当用户搜索数据时候,再根据权重将结果排名、打分 将返回结果呈现给用户 Elasticsearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。
相关文章
|
2月前
|
存储 JSON 监控
大数据-167 ELK Elasticsearch 详细介绍 特点 分片 查询
大数据-167 ELK Elasticsearch 详细介绍 特点 分片 查询
57 4
|
2月前
|
自然语言处理 搜索推荐 Java
SpringBoot 搜索引擎 海量数据 Elasticsearch-7 es上手指南 毫秒级查询 包括 版本选型、操作内容、结果截图(一)
SpringBoot 搜索引擎 海量数据 Elasticsearch-7 es上手指南 毫秒级查询 包括 版本选型、操作内容、结果截图
58 0
|
2月前
|
存储 自然语言处理 搜索推荐
SpringBoot 搜索引擎 海量数据 Elasticsearch-7 es上手指南 毫秒级查询 包括 版本选型、操作内容、结果截图(二)
SpringBoot 搜索引擎 海量数据 Elasticsearch-7 es上手指南 毫秒级查询 包括 版本选型、操作内容、结果截图(二)
40 0
|
3月前
|
JSON 自然语言处理 算法
ElasticSearch基础2——DSL查询文档,黑马旅游项目查询功能
DSL查询文档、RestClient查询文档、全文检索查询、精准查询、复合查询、地理坐标查询、分页、排序、高亮、黑马旅游案例
ElasticSearch基础2——DSL查询文档,黑马旅游项目查询功能
|
4月前
|
自然语言处理 Java 关系型数据库
ElasticSearch 实现分词全文检索 - 聚合查询 cardinality
ElasticSearch 实现分词全文检索 - 聚合查询 cardinality
155 1
|
4月前
|
存储 自然语言处理 Java
ElasticSearch 实现分词全文检索 - 经纬度定位商家距离查询
ElasticSearch 实现分词全文检索 - 经纬度定位商家距离查询
59 0
|
4月前
|
自然语言处理 Java
ElasticSearch 实现分词全文检索 - 高亮查询
ElasticSearch 实现分词全文检索 - 高亮查询
78 0
|
4月前
|
缓存 自然语言处理 Java
ElasticSearch 实现分词全文检索 - filter查询
ElasticSearch 实现分词全文检索 - filter查询
49 0
|
4月前
|
自然语言处理 Java
ElasticSearch 实现分词全文检索 - 复合查询
ElasticSearch 实现分词全文检索 - 复合查询
65 0
|
4月前
|
自然语言处理 Java 关系型数据库
ElasticSearch 实现分词全文检索 - id、ids、prefix、fuzzy、wildcard、range、regexp 查询
ElasticSearch 实现分词全文检索 - id、ids、prefix、fuzzy、wildcard、range、regexp 查询
120 0

热门文章

最新文章

相关产品

  • 检索分析服务 Elasticsearch版
  • 下一篇
    DataWorks