在elasticsearch中使用"union"进行子查询

iLi*_*ast 5 php elasticsearch elastica

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

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

列出每页25个广告.在这25个中,显示的10个广告必须是"付费广告",其他15个必须是"免费".所有25个必须与所执行的搜索相关(即关键字,地区,价格,类别等)

我知道我可以使用两个单独的查询来做到这一点,但这似乎是一种巨大的资源浪费.是否可以进行"子查询"(如果你可以调用它们?)并将这些结果合并到一个结果集中?不知怎的,只在一个查询中从elasticsearch获取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"
       },
       ...
}
Run Code Online (Sandbox Code Playgroud)

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

Joh*_*one 6

您可以采取几种方法.

首先,您可以尝试使用多搜索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}
'
Run Code Online (Sandbox Code Playgroud)

我已经编写了字段和查询,但总的来说你应该得到这个想法 - 你点击_msearch端点并传递一系列以空括号开头的查询{}.对于付费,我将大小设置为10,而对于免费,我将大小设置为15.

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

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

限制过滤器

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

{
    "filtered" : {
        "filter" : {
             "limit" : {"value" : 100}
         },
         "query" : {
            "term" : { "name.first" : "shay" }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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