一尘不染

在ElasticSearch中过滤,嵌套的inner_hits查询上的聚合

elasticsearch

我刚开始使用ElasticSearch几天,而作为一项学习练习,我实施了一个基本的工作搜寻器,该工作收集器汇总了一些求职网站上的工作,并在其中填充了一些数据供我使用。

我的索引包含每个列出职位的网站的文档。每个文档的一个属性是一个“作业”数组,其中包含该站点上存在的每个作业的对象。我正在考虑将每个作业作为自己的文档建立索引(特别是因为ElasticSearch文档说inner_hits是实验性功能),但现在,我试图查看是否可以使用ElasticSearch的inner_hits和嵌套功能来完成我想做的事情。

我能够查询,过滤并仅返回匹配的作业。但是,我不确定如何将相同的inner_hits约束应用于聚合。

这是我的映射:

{
  "jobsitesIdx" : {
    "mappings" : {
      "sites" : {
        "properties" : {
          "createdAt" : {
            "type" : "date",
            "format" : "dateOptionalTime"
          },
          "jobs" : {
            "type" : "nested",
            "properties" : {
              "company" : {
                "type" : "string"
              },
              "engagement" : {
                "type" : "string"
              },
              "link" : {
                "type" : "string",
                "index" : "not_analyzed"
              },
              "location" : {
                "type" : "string",
                "fields" : {
                  "raw" : {
                    "type" : "string",
                    "index" : "not_analyzed"
                  }
                }
              },
              "title" : {
                "type" : "string"
              }
            }
          },
          "jobscount" : {
            "type" : "long"
          },
          "sitename" : {
            "type" : "string"
          },
          "url" : {
            "type" : "string"
          }
        }
      }
    }
  }
}

这是我正在尝试的查询和汇总(来自Node.js):

client.search({
  "index": 'jobsitesIdx,
  "type": 'sites',
  "body": {


    "aggs" : {
            "jobs" : {
                "nested" : {
                    "path" : "jobs"
                },
                "aggs" : {
                    "location" : { "terms" : { "field" : "jobs.location.raw", "size": 25 } },
                    "company" : { "terms" : { "field" : "jobs.company.raw", "size": 25 } }
                }
            }
        },


    "query": {
        "filtered": {
          "query": {"match_all": {}},
          "filter": {
            "nested": {
              "inner_hits" : { "size": 1000 },
              "path": "jobs",
              "query":{
                "filtered": {
                  "query": { "match_all": {}},
                  "filter": {
                    "and": [
                      {"term": {"jobs.location": "york"}},
                      {"term": {"jobs.location": "new"}}
                    ]
                  }
                }
              }
            }
          }
        }
      }
  }
}, function (error, response) {
    response.hits.hits.forEach(function(jobsite) {
    jobs = jobsite.inner_hits.jobs.hits.hits;

    jobs.forEach(function(job) {
        console.log(job);
    });

});

    console.log(response.aggregations.jobs.location.buckets);
});

这将我带回了纽约的所有inner_hits职位,但是汇总显示了我对每个地点和公司的计数,而不仅仅是与inner_hits匹配的职位。

关于如何仅对匹配的inner_hits中包含的数据进行汇总的任何建议?

编辑:我正在对此进行更新,以根据要求包括映射和索引数据的导出。我使用Taskrabbit的elasticdump工具导出了该文件,可在此处找到:https : //github.com/taskrabbit/elasticsearch-
dump

索引:http :
//pastebin.com/WaZwBwn4
映射:http :
//pastebin.com/ZkGnYN94

上面链接的数据与我原来的问题中的示例代码不同,在于该索引在数据中的名称为Jobites6,而不是该问题中提到的JobsIdsIDx。同样,数据中的类型为“作业”,而在上面的代码中为“站点”。

我已经在上面的代码中填写了回调以显示响应数据。正如预期的那样,我仅从inner_hits的foreach循环中看到纽约的工作,但是我看到此位置汇总:

[ { key: 'New York, NY', doc_count: 243 },
  { key: 'San Francisco, CA', doc_count: 92 },
  { key: 'Chicago, IL', doc_count: 43 },
  { key: 'Boston, MA', doc_count: 39 },
  { key: 'Berlin, Germany', doc_count: 22 },
  { key: 'Seattle, WA', doc_count: 22 },
  { key: 'Los Angeles, CA', doc_count: 20 },
  { key: 'Austin, TX', doc_count: 18 },
  { key: 'Anywhere', doc_count: 16 },
  { key: 'Cupertino, CA', doc_count: 15 },
  { key: 'Washington D.C.', doc_count: 14 },
  { key: 'United States', doc_count: 11 },
  { key: 'Atlanta, GA', doc_count: 10 },
  { key: 'London, UK', doc_count: 10 },
  { key: 'Ulm, Deutschland', doc_count: 10 },
  { key: 'Riverton, UT', doc_count: 9 },
  { key: 'San Diego, CA', doc_count: 9 },
  { key: 'Charlotte, NC', doc_count: 8 },
  { key: 'Irvine, CA', doc_count: 8 },
  { key: 'London', doc_count: 8 },
  { key: 'San Mateo, CA', doc_count: 8 },
  { key: 'Boulder, CO', doc_count: 7 },
  { key: 'Houston, TX', doc_count: 7 },
  { key: 'Palo Alto, CA', doc_count: 7 },
  { key: 'Sydney, Australia', doc_count: 7 } ]

由于我的inner_hits仅限于在纽约的那些,因此我可以看到该聚合未包含在我的inner_hits上,因为它可以为我提供所有地点的计数。


阅读 1635

收藏
2020-06-22

共1个答案

一尘不染

您可以通过在聚合中添加相同的过滤器以仅包括纽约作业来实现此目的。另请注意,在您进行的第二次汇总中,company.raw但在映射中,该jobs.company字段没有not_analyzed名为的部分raw,因此,如果您要汇总未分析的公司名称,则可能需要添加它。

{
  "_source": [
    "sitename"
  ],
  "query": {
    "filtered": {
      "filter": {
        "nested": {
          "inner_hits": {
            "size": 1000
          },
          "path": "jobs",
          "query": {
            "filtered": {
              "filter": {
                "terms": {
                  "jobs.location": [
                    "new",
                    "york"
                  ]
                }
              }
            }
          }
        }
      }
    }
  },
  "aggs": {
    "jobs": {
      "nested": {
        "path": "jobs"
      },
      "aggs": {
        "only_loc": {
          "filter": {            <----- add this filter
            "terms": {
              "jobs.location": [
                "new",
                "york"
              ]
            }
          },
          "aggs": {
            "location": {
              "terms": {
                "field": "jobs.location.raw",
                "size": 25
              }
            },
            "company": {
              "terms": {
                "field": "jobs.company",
                "size": 25
              }
            }
          }
        }
      }
    }
  }
}
2020-06-22