Elasticsearch percolate 查询示例详解
作者:Elasticsearch 发布时间:2021-07-15 04:57:54
Elasticsearch 通常如何工作?
我们将文档索引到 Elasticsearch 中并对其运行查询以获得满足提供的搜索条件的文档。 我们构造一个匹配或术语查询作为输入,匹配查询的文档作为结果返回。
但这不是 percolate query 的情况.....
让我们看看这篇文章中的 percolate 查询,看看它有什么用处。
什么是 percolate 查询?
它与 Elasticsearch 搜索的一般工作方式相反。 在 Percolate Query 中,你将提供文档作为输入,以从与输入文档匹配的索引中查找 query。 可以根据已保存的查询使用 Percolate Query 对文档进行分类或标记。
Percolate query 调用 Elasticsearch 经典搜索的逆向 因为,
query 将被存储而不是 Elasticsearch 索引中的文档。
文档将用于代替搜索请求中的 query。
Elasticsearch 将生成与输入文档匹配的查询列表。
你可能想知道为什么我需要 Percolate 以及如何使用它? 因此,让我们看看下面的一些用例。
Percolate 用例
基于 percolate query 上面的描述,我们可以把它应用于如下的一些查询用例:
假设你正在开发一家在线商店,并提供在特定产品在特定价格范围内或以特定折扣上市时创建提醒的功能。
你正在创建推文或帖子分析,并且需要只考虑符合特定条款或条件的内容。 此外,每条满足特定要求的推文或帖子都需要使用特定标签进行标记。
Percolate query 实施
让我们通过一个在线商店用例来更详细地探索 Percolate。
假设消费者希望在 Apple iPhone 12 售价 500 美元时收到通知。
brand:apple AND price<500 AND model:'iphone 12'
使用一些示例数据创建 products 索引:
`
PUT products
{
"mappings": {
"properties": {
"brand": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword"
}
}
},
"model": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword"
}
}
},
"price": {
"type": "long"
}
}
}
}
PUT products/_bulk
{ "index" : { "_id": "prod101" } }
{ "brand" : "Apple", "model" : "iphone 11", "price": 800 }
{ "index" : { "_id": "prod102" } }
{ "brand" : "Samsung", "model" : "galaxy m32", "price": 700 }
`
创建 percolate 索引:
必须将原始索引中的相同字段映射添加到 percolate 索引中。 只有需要搜索的字段必须从原始索引的映射中复制。
`
PUT product_percolate
{
"mappings": {
"properties": {
"query": {
"type": "percolator"
},
"brand": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword"
}
}
},
"model": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword"
}
}
},
"price": {
"type": "long"
}
}
}
}
`
让我们保存一个用户想要提醒的 query:
`
PUT product_percolate/_doc/user1_iphone_12
{
"query": {
"bool": {
"must": [
{
"term": {
"brand.keyword": {
"value": "Apple"
}
}
},
{
"term": {
"model.keyword": {
"value": "iphone 12"
}
}
},
{
"range": {
"price": {
"lte": 500
}
}
}
]
}
}
}
`
现在进行产品查询时,将不会返回任何结果,因为所有 iPhone 12 不低于 500 美元。
`
POST products/_search
{
"query": {
"bool": {
"must": [
{
"term": {
"brand.keyword": {
"value": "Apple"
}
}
},
{
"term": {
"model.keyword": {
"value": "iphone 12"
}
}
},
{
"range": {
"price": {
"lte": 500
}
}
}
]
}
}
}
`
上面的搜索将返回如下的结果:
`
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 0,
"relation": "eq"
},
"max_score": null,
"hits": []
}
}
`
上面的结果表明,没有一个产品满足我们的搜索条件。
让我们添加价格为 499 的新产品 iPhone 12:
POST product/_doc/prod104
{
"brand": "Apple",
"model": "iphone 12",
"price": 499
}
不会发送自动通知,因为在索引文档时不会运行 percolate 查询。 percolate 查询必须手动运行。
Percolate query API
你可以通过两种方式执行 percolate query:
首先,你可以使用单个文档或多个文档作为输入运行 percolate,如下所示:
单个文档
GET product_percolate/_search
{
"query": {
"percolate": {
"field": "query",
"document": {
"brand": "Apple",
"model": "iphone 12",
"price": 499
}
}
}
}
多个文档
`
GET product_percolate/_search
{
"query": {
"percolate": {
"field": "query",
"documents": [
{
"brand": "Apple",
"model": "iphone 12 pro",
"price": 600
},
{
"brand": "Apple",
"model": "iphone 12",
"price": 499
}
]
}
}
}
`
你将收到类似于正常查询响应的响应,字段 _source 将显示匹配的查询,但字段 _percolator_document_slot 将显示在这种情况下多个文档中匹配的文档的位置。
`
{
"took": 3,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 1.2615292,
"hits": [
{
"_index": "product_percolate",
"_id": "user1_iphone_12",
"_score": 1.2615292,
"_source": {
"query": {
"bool": {
"must": [
{
"term": {
"brand.keyword": {
"value": "Apple"
}
}
},
{
"term": {
"model.keyword": {
"value": "iphone 12"
}
}
},
{
"range": {
"price": {
"lte": 500
}
}
}
]
}
}
},
"fields": {
"_percolator_document_slot": [
0
]
}
}
]
}
}
`
其次,你可以提供现有索引中的文档 ID,如下所示(目前不支持传递多个 ID):
GET product_percolate/_search
{
"query": {
"percolate": {
"field": "query",
"index": "product",
"id": "prod104"
}
}
}
上面的查询的结果为:
`
{
"took": 7,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 1.2615292,
"hits": [
{
"_index": "product_percolate",
"_id": "user1_iphone_12",
"_score": 1.2615292,
"_source": {
"query": {
"bool": {
"must": [
{
"term": {
"brand.keyword": {
"value": "Apple"
}
}
},
{
"term": {
"model.keyword": {
"value": "iphone 12"
}
}
},
{
"range": {
"price": {
"lte": 500
}
}
}
]
}
}
},
"fields": {
"_percolator_document_slot": [
0
]
}
}
]
}
}
`
如何将 Percolate 与你的应用程序集成
如果你使用 Logstash 为数据编制索引,则可以使用 Elasticsearch 过滤器插件并运行过滤查询以查看传入文档是否与任何已保存的查询匹配。 如果是这样,你可以使用单独的输出插件向用户发送通知。
如果自定义连接器用于数据索引,则 Elastic 客户端可用于运行 percolate query 并直接从连接器发送通知。
为什么要 percolate 而不是 watcher?
相对于percolate,watcher 不太适合需要实时匹配的场景。 是的,相比之下还有更多的争论空间,但暂时,我认为这不在本博客的范围之内。
来源:https://juejin.cn/post/7192431517467934776


猜你喜欢
- 需求分析:我们在做winform开发的时候,有时候需要让程序休眠几秒钟,但是如果我们直接使用 Thread.Sleep()函数的话,页面UI
- 在开始之前,我先卖个关子提一个问题:假设我们有一个Movie类,这个类有三个成员变量分别是starred(是否收藏), title(电影名称
- 实现Java编程中倒计时的方法有许多,下面我们通过三个
- 1.短信平台购买次数地址https://market.aliyun.com/products/57000002/cmapi00046920.
- 在项目中如果涉及到用Excel开发的报表模版来导出报表数据的话,一般都是在Excel报表中使用VBA做成宏来进行调用。即先使用Excel自带
- 对过滤器doFilter里chain.doFilter()函数的理解关于chain.doFilter()函数在最近的使用中不是很理解,但是考
- 三个例子 —JAVA发送http get/post请求,调用http接口、方法例1:使用 HttpClient (commons-httpc
- Java实现按行读取大文件String file = "F:" + File.separator + "a.t
- 背景何为延迟队列?顾名思义,延迟队列就是进入该队列的消息会被延迟消费的队列。而一般的队列,消息一旦入队了之后就会被消费者马上消费。场景一:在
- 一般振动时间的配置在如下文件:frameworks/base/core/res/res/values/config.xml &nb
- @PropertySource读取配置文件通过@Value参数注入有参数文件如下test.propertiesproject.author=
- 一、错误处理原理分析使用SpringBoot创建的web项目中,当我们请求的页面不存在(http状态码为404),或者器发生异常(http状
- 实验目的在C#和Rest/Restful以及其它的Web服务交互过程中,大量使用到JSON传递数据,如何快捷的转化C#对象到JSON和转化J
- TabLayout和ViewPager搭配使用,是有很多方便性,但是TabLayout这东西还是有很多被人吐槽的地方。这里只讲怎么设置tab
- 因为最近重新看了泛型,又看了些反射,导致我对Object、T(以下代指泛型)、?产生了疑惑。我们先来试着理解一下Object类,学习Java
- 前言Sharding-JDBC是ShardingSphere的第一个产品,也是ShardingSphere的前身。它定位为轻量级Java框架
- 前两天看了个扫雷的视频,于是自己跟着做了下,感觉还不是很难。初学Java的同学可以尝试自己操作下Java小程序这样子才能提高自己的理解能力和
- 先随便搞个事件吧public class TestEventrgs : EventArgs {private st
- AsyncTask,顾名思义,异步任务。说到异步,最简单的理解就是不同步。再复杂一点理解,就得举例子了。假设我要去火车站买票,刚到火车站我突
- 1、StatefulWidget的背后flutter开发过程中,我们经常会用到两个组件StatelessWidget和StatefulWid