【问题标题】:Sub-queries with "union" in elasticsearchelasticsearch中带有“union”的子查询
【发布时间】:2014-06-25 12:42:24
【问题描述】:

我目前正忙于一个项目,我们选择使用 Elasticsearch 作为分类网站的搜索引擎。

目前,我有以下业务规则:

每页列出 25 个广告。在这 25 个中,显示的广告中有 10 个必须是“付费广告”,另外 15 个必须是“免费”。所有 25 项都必须与执行的搜索相关(即关键字、地区、价格、类别等)

我知道我可以使用两个单独的查询来做到这一点,但这似乎是对资源的极大浪费。是否可以进行“子查询”(如果您可以这样称呼它们?)并将这些结果合并到一个结果集中?不知何故,在一个查询中只能从弹性搜索中获取 10 个“付费”广告和 15 个“免费”广告?当然,假设有足够多的广告使这个要求成为可能。

感谢您的帮助!

编辑 - 只需添加我的地图信息以提高清晰度。

"properties": {
       "advertText": {
          "type": "string",
          "boost": 2,
          "store": true,
          "analyzer": "snowball"
       },
       "canonical": {
          "type": "string",
          "store": true
       },
       "category": {
          "properties": {
             "id": {
                "type": "string",
                "store": true
             },
             "name": {
                "type": "string",
                "store": true
             },
             "parentCategory": {
                "type": "string",
                "store": true
             }
          }
       },
       "contactNumber": {
          "type": "string",
          "index": "not_analyzed",
          "store": true
       },
       "emailAddress": {
          "type": "string",
          "store": true,
          "analyzer": "url_email_analyzer"
       },
       "advertType": {
          "type": "string",
          "index": "not_analyzed"
       },
       ...
}

然后我想要的是能够查询并获得 10 个结果,其中“advertType”:“付费” 15 个“advertType”:“免费”...

【问题讨论】:

  • 您能分享您的映射、示例数据和每种类型的示例查询吗?对提出解决方案有很大帮助。
  • @JohnPetrone,我会在我回来工作时这样做(在 RSA 是晚上 8 点)。尽管如此,让我们将“广告”的概念完全排除在外,是否可以查询弹性搜索一次,但执行类似“获得 5 个 admins 和 10 个 people 索引中的 i>员工?我不知道如何用恰当的措辞来表达这个问题,这样才更有意义!
  • 我想我可以让你非常接近 - 我会开始写一个答案。需要一点解释。

标签: php elasticsearch elastica


【解决方案1】:

您可以采取几种方法。

首先,您可以尝试使用多搜索 API:

多搜索 API

多搜索 API 允许在其中执行多个搜索请求 相同的 API。它的端点是_msearch。

请求的格式类似于批量API格式

http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-multi-search.html

一个基本的例子:

curl -XGET 'http://127.0.0.1:9200/advertising_index/_msearch?pretty=1'  -d '
{}
{"query" : {"match" : {"Paid_Ads" : "search terms"}}, "size" : 10}
{}
{"query" : {"match" : {"Free" : "search terms"}}, "size" : 15}
'

我已经编写了字段和查询,但总的来说,您应该明白了 - 您点击 _msearch 端点并将一系列以空括号 {} 开头的查询传递给它。对于付费,我将大小设置为 10,对于免费,我将大小设置为 15。

根据您自己的实现细节,您应该能够使用这样的东西。

如果由于某种原因不起作用,您也可以尝试使用限制过滤器:

限制过滤器

限制过滤器限制要执行的文档数量(每个分片) 在。例如:

{
    "filtered" : {
        "filter" : {
             "limit" : {"value" : 100}
         },
         "query" : {
            "term" : { "name.first" : "shay" }
        }
    }
}

http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-limit-filter.html

请注意,限制是每个分片,而不是每个索引。给定每个索引的默认 5 个主分片,要获得 10 的总响应,您可以将限制设置为 2 (2X5 == 10)。另请注意,如果您在一个分片上有多个匹配项但在另一个分片上没有匹配项,这可能会产生不完整的结果。

然后您可以将两个过滤器与一个 bool 过滤器结合起来:

布尔过滤器

一个过滤器,匹配匹配其他布尔组合的文档 查询。在概念上类似于布尔查询,除了子句 是其他过滤器。可以放在接受过滤器的查询中。

http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-bool-filter.html

我没有详细说明这一点,因为它需要有关您的特定索引、映射、数据和查询的更多信息。

【讨论】:

  • 我认为第一个可能是我正在寻找的。这在性能方面如何?我的意思是多搜索端点。查询是否被缓存?它比单独执行每个查询快多少?我已经更新了我的问题以反映映射信息,如果您想要其他任何内容,请大声喊叫!感谢您的帮助!
  • 它的行为方式与批量加载 API 类似——它就像一个批量查询工具。您仍然有两个查询的成本,但只有 1 次往返和只有 1 个有效负载交付回客户端,这会对性能产生显着的积极影响。
  • 太棒了!感谢您的帮助!
  • 这里两个查询都是单独执行的。但是如果一个查询输出被作为另一个查询的输入。如何在一个 api 中做到这一点
  • 第一种方式,结果是否去重?我们可以在每个子查询中进行不同的排序吗?
【解决方案2】:

尝试使用限制返回文档数量的限制过滤器

{
"filtered" : {
    "filter" : {
         "limit" : {"value" : 10}
     },
     "query" : {
        "term" : { "name.first" : "shay" }
    }
}
}

将值更改为 2 可获得 10 个结果,将值更改为 3 可获得 15 个

【讨论】:

    【解决方案3】:

    您是在询问吗?

    (select * from tablename where advert = "Paid Advert" limit 10) union (select * from tablename where advert = "Free" limit 15);
    

    每页生成限制的逻辑?

    【讨论】:

    • 这是一个 SQL 查询。正在寻找 Elasticsearch 查询。
    猜你喜欢
    • 2022-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-16
    • 2015-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多