Link Search Menu Expand Document Documentation Menu

渗透

使用 percolate 查询查找与给定文档匹配的存储查询。此操作与常规搜索相反:您查找的是与文档匹配的查询,而不是查找与查询匹配的文档。percolate 查询常用于警报、通知和反向搜索用例。

在使用 percolate 查询时,请考虑以下关键点:

  • 您可以对内联提供的文档进行渗滤,或从索引中获取现有文档进行渗滤。
  • 文档和存储的查询必须使用相同的字段名称和类型。
  • 您可以将渗滤与过滤和评分结合使用,以构建复杂的匹配系统。
  • percolate 查询被认为是开销较大的查询,仅当集群设置 search.allow_expensive_queries 设置为 true(默认值)时才会运行。如果此设置是 falsepercolate 查询将被拒绝。

percolate 查询在各种实时匹配场景中都很有用。一些常见用例包括:

  • 电子商务通知:用户可以注册对产品的兴趣,例如“当新的 Apple 笔记本电脑有货时通知我”。当新产品文档被索引时,系统会找到所有具有匹配保存查询的用户并发送警报。
  • 职位警报:求职者根据偏好的职位名称或地点保存查询,新的职位发布会与这些查询进行匹配以触发警报。
  • 安全和警报系统:根据保存的规则或异常模式对传入的日志或事件数据进行渗滤。
  • 新闻过滤:将传入文章与保存的主题配置文件进行匹配,以分类或提供相关内容。

渗滤的工作原理

  1. 保存的查询存储在特殊的percolator 字段类型中。
  2. 文档与所有保存的查询进行比较。
  3. 每个匹配的查询都将返回其 _id
  4. 如果启用了高亮显示,匹配的文本片段也将返回。
  5. 如果发送了多个文档,_percolator_document_slot 将显示匹配的文档。

示例

以下示例演示了如何存储 percolate 查询,并使用不同方法对文档进行测试。

创建一个用于存储保存查询的索引

首先,创建一个索引并使用percolator 字段类型配置其 mappings 以存储保存的查询

PUT /my_percolator_index
{
  "mappings": {
    "properties": {
      "query": {
        "type": "percolator"
      },
      "title": {
        "type": "text"
      }
    }
  }
}

title 字段中添加匹配“apple”的查询

POST /my_percolator_index/_doc/1
{
  "query": {
    "match": {
      "title": "apple"
    }
  }
}

title 字段中添加匹配“banana”的查询

POST /my_percolator_index/_doc/2
{
  "query": {
    "match": {
      "title": "banana"
    }
  }
}

渗滤内联文档

对照保存的查询测试内联文档

POST /my_percolator_index/_search
{
  "query": {
    "percolate": {
      "field": "query",
      "document": {
        "title": "Fresh Apple Harvest"
      }
    }
  }
}

响应提供了存储的 percolate 查询,该查询搜索 title 字段中包含单词“apple”的文档,由 _id: 1 标识

{
  ...
  "hits": {
    "total": {
      "value": 1,
      "relation": "eq"
    },
    "max_score": 0.13076457,
    "hits": [
      {
        "_index": "my_percolator_index",
        "_id": "1",
        "_score": 0.13076457,
        "_source": {
          "query": {
            "match": {
              "title": "apple"
            }
          }
        },
        "fields": {
          "_percolator_document_slot": [
            0
          ]
        }
      }
    ]
  }
}

渗滤多个文档

要在同一个查询中测试多个文档,请使用以下请求

POST /my_percolator_index/_search
{
  "query": {
    "percolate": {
      "field": "query",
      "documents": [
        { "title": "Banana flavoured ice-cream" },
        { "title": "Apple pie recipe" },
        { "title": "Banana bread instructions" },
        { "title": "Cherry tart" }
      ]
    }
  }
}

_percolator_document_slot 字段帮助您识别每个(按索引)与每个保存查询匹配的文档

{
  ...
  "hits": {
    "total": {
      "value": 2,
      "relation": "eq"
    },
    "max_score": 0.54726034,
    "hits": [
      {
        "_index": "my_percolator_index",
        "_id": "1",
        "_score": 0.54726034,
        "_source": {
          "query": {
            "match": {
              "title": "apple"
            }
          }
        },
        "fields": {
          "_percolator_document_slot": [
            1
          ]
        }
      },
      {
        "_index": "my_percolator_index",
        "_id": "2",
        "_score": 0.31506687,
        "_source": {
          "query": {
            "match": {
              "title": "banana"
            }
          }
        },
        "fields": {
          "_percolator_document_slot": [
            0,
            2
          ]
        }
      }
    ]
  }
}

渗滤现有已索引文档

您可以引用已存储在另一个索引中的现有文档,以检查匹配的 percolate 查询。

为您的文档创建一个单独的索引

PUT /products
{
  "mappings": {
    "properties": {
      "title": {
        "type": "text"
      }
    }
  }
}

添加文档

POST /products/_doc/1
{
  "title": "Banana Smoothie Special"
}

检查存储的查询是否与已索引文档匹配

POST /my_percolator_index/_search
{
  "query": {
    "percolate": {
      "field": "query",
      "index": "products",
      "id": "1"
    }
  }
}

当使用存储的文档时,您必须同时提供 indexid

返回相应的查询

{
  ...
  "hits": {
    "total": {
      "value": 1,
      "relation": "eq"
    },
    "max_score": 0.13076457,
    "hits": [
      {
        "_index": "my_percolator_index",
        "_id": "2",
        "_score": 0.13076457,
        "_source": {
          "query": {
            "match": {
              "title": "banana"
            }
          }
        },
        "fields": {
          "_percolator_document_slot": [
            0
          ]
        }
      }
    ]
  }
}

批量渗滤(多个文档)

您可以在一个请求中检查多个文档

POST /my_percolator_index/_search
{
  "query": {
    "percolate": {
      "field": "query",
      "documents": [
        { "title": "Apple event coming soon" },
        { "title": "Banana farms expand" },
        { "title": "Cherry season starts" }
      ]
    }
  }
}

每个匹配项都在 _percolator_document_slot 字段中指示匹配的文档

{
  ...
  "hits": {
    "total": {
      "value": 2,
      "relation": "eq"
    },
    "max_score": 0.46484798,
    "hits": [
      {
        "_index": "my_percolator_index",
        "_id": "2",
        "_score": 0.46484798,
        "_source": {
          "query": {
            "match": {
              "title": "banana"
            }
          }
        },
        "fields": {
          "_percolator_document_slot": [
            1
          ]
        }
      },
      {
        "_index": "my_percolator_index",
        "_id": "1",
        "_score": 0.41211313,
        "_source": {
          "query": {
            "match": {
              "title": "apple"
            }
          }
        },
        "fields": {
          "_percolator_document_slot": [
            0
          ]
        }
      }
    ]
  }
}

使用命名查询的多查询渗滤

您可以在命名查询中渗滤不同的文档

GET /my_percolator_index/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "percolate": {
            "field": "query",
            "document": {
              "title": "Apple pie recipe"
            },
            "name": "apple_doc"
          }
        },
        {
          "percolate": {
            "field": "query",
            "document": {
              "title": "Banana bread instructions"
            },
            "name": "banana_doc"
          }
        }
      ]
    }
  }
}

name 参数被附加到 _percolator_document_slot,以提供匹配的查询

{
  ...
  "hits": {
    "total": {
      "value": 2,
      "relation": "eq"
    },
    "max_score": 0.13076457,
    "hits": [
      {
        "_index": "my_percolator_index",
        "_id": "1",
        "_score": 0.13076457,
        "_source": {
          "query": {
            "match": {
              "title": "apple"
            }
          }
        },
        "fields": {
          "_percolator_document_slot_apple_doc": [
            0
          ]
        }
      },
      {
        "_index": "my_percolator_index",
        "_id": "2",
        "_score": 0.13076457,
        "_source": {
          "query": {
            "match": {
              "title": "banana"
            }
          }
        },
        "fields": {
          "_percolator_document_slot_banana_doc": [
            0
          ]
        }
      }
    ]
  }
}

此方法使您能够为单个文档配置更自定义的查询逻辑。在以下示例中,第一个文档查询 title 字段,第二个文档查询 description 字段。还提供了 boost 参数

GET /my_percolator_index/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "constant_score": {
            "filter": {
              "percolate": {
                "field": "query",
                "document": {
                  "title": "Apple pie recipe"
                },
                "name": "apple_doc"
              }
            },
            "boost": 1.0
          }
        },
        {
          "constant_score": {
            "filter": {
              "percolate": {
                "field": "query",
                "document": {
                  "description": "Banana bread with honey"
                },
                "name": "banana_doc"
              }
            },
            "boost": 3.0
          }
        }
      ]
    }
  }
}

批量渗滤与命名渗滤的比较

批量渗滤(使用 documents)和命名渗滤(使用带 namebool)都可以用于渗滤多个文档,但它们在结果的标签、解释和控制方式上有所不同。它们提供功能相似的结果,但存在重要的结构差异,如下表所述。

功能 批量(documents 命名(bool + percolate + name
输入格式 一个渗滤子句,文档数组 多个渗滤子句,每个文档一个
每文档可追溯性 按槽位索引 (0, 1, …) 按名称(apple_doc, banana_doc
匹配槽位的响应字段 _percolator_document_slot: [0] _percolator_document_slot_: [0]
高亮前缀 0_title, 1_title apple_doc_title, banana_doc_title
每文档自定义控制 不支持 可以自定义每个子句
支持提升和过滤 是(每个子句)
性能 最适合大型批量 子句较多时略慢
用例 批量匹配作业,大型事件流 每文档跟踪、测试、自定义控制

高亮显示匹配项

percolate 查询处理高亮显示的方式与常规查询不同

  • 在常规查询中,文档存储在索引中,搜索查询用于高亮显示匹配的词项。
  • percolate 查询中,角色是反向的:保存的查询(在渗滤器索引中)用于高亮显示文档。

这意味着 documentdocuments 中提供的文档是高亮显示的目标,并且 percolate 查询决定了要高亮的区域。

高亮显示单个文档

此示例使用之前在 my_percolator_index 中定义的搜索。使用以下请求高亮显示 title 字段中的匹配项:

POST /my_percolator_index/_search
{
  "query": {
    "percolate": {
      "field": "query",
      "document": {
        "title": "Apple banana smoothie"
      }
    }
  },
  "highlight": {
    "fields": {
      "title": {}
    }
  }
}

匹配项根据匹配的查询进行高亮显示

{
  ...
  "hits": {
    "total": {
      "value": 2,
      "relation": "eq"
    },
    "max_score": 0.13076457,
    "hits": [
      {
        "_index": "my_percolator_index",
        "_id": "1",
        "_score": 0.13076457,
        "_source": {
          "query": {
            "match": {
              "title": "apple"
            }
          }
        },
        "fields": {
          "_percolator_document_slot": [
            0
          ]
        },
        "highlight": {
          "title": [
            "<em>Apple</em> banana smoothie"
          ]
        }
      },
      {
        "_index": "my_percolator_index",
        "_id": "2",
        "_score": 0.13076457,
        "_source": {
          "query": {
            "match": {
              "title": "banana"
            }
          }
        },
        "fields": {
          "_percolator_document_slot": [
            0
          ]
        },
        "highlight": {
          "title": [
            "Apple <em>banana</em> smoothie"
          ]
        }
      }
    ]
  }
}

高亮显示多个文档

当使用 documents 数组渗滤多个文档时,每个文档都会被分配一个槽位索引。高亮键然后采用以下形式,其中 <slot> 是文档在您的 documents 数组中的索引:

"<slot>_<fieldname>": [ ... ]

使用以下命令渗滤两个文档并高亮显示:

POST /my_percolator_index/_search
{
  "query": {
    "percolate": {
      "field": "query",
      "documents": [
        { "title": "Apple pie recipe" },
        { "title": "Banana smoothie ideas" }
      ]
    }
  },
  "highlight": {
    "fields": {
      "title": {}
    }
  }
}

响应包含以文档槽位为前缀的高亮字段,例如 0_title1_title

{
  ...
  "hits": {
    "total": {
      "value": 2,
      "relation": "eq"
    },
    "max_score": 0.31506687,
    "hits": [
      {
        "_index": "my_percolator_index",
        "_id": "1",
        "_score": 0.31506687,
        "_source": {
          "query": {
            "match": {
              "title": "apple"
            }
          }
        },
        "fields": {
          "_percolator_document_slot": [
            0
          ]
        },
        "highlight": {
          "0_title": [
            "<em>Apple</em> pie recipe"
          ]
        }
      },
      {
        "_index": "my_percolator_index",
        "_id": "2",
        "_score": 0.31506687,
        "_source": {
          "query": {
            "match": {
              "title": "banana"
            }
          }
        },
        "fields": {
          "_percolator_document_slot": [
            1
          ]
        },
        "highlight": {
          "1_title": [
            "<em>Banana</em> smoothie ideas"
          ]
        }
      }
    ]
  }
}

参数

percolate 查询支持以下参数。

参数 必需/可选 描述
field 必需 包含存储的 percolate 查询的字段。
document 可选 一个用于与保存查询匹配的单个内联文档。
documents 可选 一个用于与保存查询匹配的多个内联文档数组。
index 可选 包含您要匹配的文档的索引。
id 可选 要从索引中获取的文档 ID。
路由 可选 获取文档时要使用的路由值。
preference 可选 获取文档时分片路由的偏好设置。
名称 可选 分配给 percolate 子句的名称。在使用 bool 查询中的多个 percolate 子句时很有用。