首页 > 解决方案 > Elasticsearch:获取特定商品的订购号

问题描述

在同行业的公司中,我需要选择收入最高的前 5 家公司,以及哪个公司在该行业中排名。编写第一个查询很容易:

GET myIndex/_search
{
  "from": 0, 
  "size": 5, 
  "query": {
    "match": {
      "industryCode": "xxxx"
    }
  },
  "sort": [
    {
      "revenue": {
        "order": "desc"
      }
    }
  ]
}

但我不知道如何编写第二个查询。目前,我必须使用滚动功能来扫描同行业公司的所有记录,如下所示:

async Task<int> GetRank()
{
    int rank = 0;
    searchRequest.Size = 500;
    searchRequest.From = 0;
    searchRequest.Scroll = "1m";

    var rs = await _elasticClient.SearchAsync<Tmp>(searchRequest);

    while (rs.Documents.Count > 0)
    {
        foreach (var item in rs.Documents)
        {
            rank++;
            if (item.OrganCode == request.OrganCode) return rank;
        }
        rs = _elasticClient.Scroll<Tmp>("1m", rs.ScrollId);
    }

    return rank;
}

这种方法真的很慢,如果公司收入很低,可能需要几分钟才能产生结果。有没有办法解决这个问题?非常感谢!!!

标签: c#elasticsearchnest

解决方案


如果我正确理解您的问题,您希望获得收入最高的前 5 家公司,按行业代码分组。这可以通过terms聚合和top_hits子聚合来完成

{
  "aggs": {
    "industry_codes": {
      "aggs": {
        "top_companies": {
          "top_hits": {
            "size": 5,
            "sort": [
              {
                "revenue": {
                  "order": "desc"
                }
              }
            ]
          }
        }
      },
      "terms": {
        "field": "industryCode"
      }
    }
  },
  "size": 0
}

在 NEST 中,这看起来像

var client = new ElasticClient(settings);

var searchResponse = client.Search<Tmp>(s => s
    .Size(0)
    .Aggregations(a => a
        .Terms("industry_codes", t => t
            .Field(f => f.IndustryCode)
            .Aggregations(aa => aa
                .TopHits("top_companies", th => th
                    .Sort(so => so
                        .Descending(f => f.Revenue)
                    )
                    .Size(5)
                )   
            )
        )
    )
);

获取每个行业代码的热门信息

var termsAgg = searchResponse.Aggregations.Terms("industry_codes");

foreach (var bucket in termsAgg.Buckets)
{
    var topHits = bucket.TopHits("top_companies");
    
    foreach (var company in topHits.Documents<Tmp>())
    {
        // do something with company        
    }
}

推荐阅读