如何使用NEST进行过滤器聚合? [英] How to make Filter Aggregations using NEST?

查看:63
本文介绍了如何使用NEST进行过滤器聚合?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要使用NEST进行过滤器聚合.但是由于对此我不太了解,所以我做了以下内容:

I have a requirement for filter aggregations using NEST. But since I don't know much about this, I have made the below:

class Program
{
        static void Main(string[] args)
        {

            ISearchResponse<TestReportModel> searchResponse =
                            ConnectionToES.EsClient()
                            .Search<TestReportModel>
                            (s => s
                                .Index("feedbackdata")
                                .From(0)
                                .Size(50000)
                                .Query(q =>q.MatchAll())
                            );
                            
            var testRecords = searchResponse.Documents.ToList<TestReportModel>();
                
            result = ComputeTrailGap(testRecords);

        }
        
        
        private static List<TestModel> ComputeTrailGap(List<TestReportModel> testRecords)
        {
            var objTestModel = new List<TestModel>();          
            
            var ptpDispositionCodes = new string[] { "PTP" };
            var bptpDispositionCodes = new string[] { "BPTP","SBPTP" };
                  

            int gapResult = testRecords.Where(w => w.trailstatus == "Gap").Count();           

            var ptpResult = testRecords.Where(w => ptpDispositionCodes.Contains(w.lastdispositioncode)).ToList().Count();

            var bptpResult = testRecords.Where(w => bptpDispositionCodes.Contains(w.lastdispositioncode)).ToList().Count();
           

            objTestModel.Add(new TestModel { TrailStatus = "Gap", NoOfAccounts = gapResult });           
            objTestModel.Add(new TestModel { TrailStatus = "PTP", NoOfAccounts = ptpResult });
            objTestModel.Add(new TestModel { TrailStatus = "BPTP", NoOfAccounts = bptpResult });         

            return objTestModel;
        }
}

DTO

public class TestReportModel
{
   
    public string trailstatus { get; set; }        
    public string lastdispositioncode { get; set; }        
}

public class TestOutputAPIModel
{
    public List<TestModel> TestModelDetail { get; set; }    
}

public class TestModel
{   
    public string TrailStatus { get; set; }
    public int NoOfAccounts { get; set; }
    
}

该程序有效,但可以确定我们仅通过NEST访问Elastic Search,其余的聚合/过滤器使用Lambda完成.

This program works but as can be figure out that we are only accessing the Elastic Search via NEST and the rest of the Aggregations /Filter are done using Lambda.

我想使用NEST框架执行整个操作(聚合/过滤器等),然后使用过滤器聚合将其放入TestModel中.

I would like to perform the entire operation (Aggregations /Filter etc) using NEST framework and put it in the TestModel using filter aggregation.

如何在NEST内部构造DSL查询?

How can I construct the DSL query inside NEST?

到目前为止,我已经达到了以下标准,但计数为零.我的查询构造有什么问题?

I have been able to make the below so far but the count is zero. What is wrong in my query construction?

var ptpDispositionCodes = new TermsQuery
            {
                IsVerbatim = true,
                Field = "lastdispositioncode",
                Terms = new string[] { "PTP" },
            };
var bptpDispositionCodes = new TermsQuery
{
    IsVerbatim = true,
    Field = "lastdispositioncode",
    Terms = new string[] { "BPTP" },
};

 ISearchResponse<TestReportModel> searchResponse =
                ConnectionToES.EsClient()
                .Search<TestReportModel>
                (s => s
                    .Index("feedbackdata")
                    .From(0)
                    .Size(50000)
                    .Query(q =>q.MatchAll())
                    .Aggregations(fa => fa

                        .Filter("ptp_aggs", f => f.Filter(fd => ptpDispositionCodes))
                        .Filter("bptp_aggs", f => f.Filter(fd => bptpDispositionCodes))

                        )
               );

结果

推荐答案

我看到您正在尝试对 TestReportModel 类型进行搜索.您的方法的总体结构似乎足够好.但是,附加到过滤器容器的查询会出现问题.

I see that you are trying to perform a search on the type of TestReportModel. The overall structure of your approach seems good enough. However, there is a trouble with the queries that are being attached to your filter containers.

您的 TestReportModel 包含两个属性 trialStatus lastdispositioncode .您要在 terms 查询中将 Field 属性设置为 description .这就是您将计数视为零的原因.您要在其上进行搜索的模型(反过来,您要在其上进行搜索的索引)没有属性 description ,因此没有区别. NEST 或Elasticsearch,在这种情况下不会引发任何异常.而是返回零计数. Field 的值应修改为 lastdispositioncode .

Your TestReportModel contains two properties trialStatus and lastdispositioncode. You are setting the Field property as description inside your terms query. This is the reason that you are seeing the counts as zero. The model on which you are performing the search on (in turn the index that you are performing the search on) does not have a property description and hence the difference. NEST or Elasticsearch, in this case does not throw any exception. Instead, it returns count zero. Field value should be modified to lastdispositioncode.

// Type on which the search is being performed. 
// Response is of the type ISearchResponse<TestReportModel>
public class TestReportModel
{
    public string trailstatus { get; set; }        
    public string lastdispositioncode { get; set; }        
}

修改的条款查询如下

// Field is "lastdispositioncode" and not "description"
// You may amend the Terms field as applicable
var ptpDispositionCodes = new TermsQuery
{
    IsVerbatim = true,
    Field = "lastdispositioncode",
    Terms = new string[] { "PTP" },
};

var bptpDispositionCodes = new TermsQuery
{
    IsVerbatim = true,
    Field = "lastdispositioncode",
    Terms = new string[] { "BPTP", "SBPTP" },
};

由于似乎 lastdispositioncode 的值似乎采用单个单词值(示例中为PTP或BPTP),所以我认为,文档中的字段是否为分析与否.您可以进一步从 ISearchResponse< T> 类型获取计数,如下所示

Since it seems that the values to lastdispositioncode seem to take a single word value (PTP or BPTP from your examples), I believe, it is not going to matter if the field in the doc is analyzed or not. You can further obtain the counts from the ISearchResponse<T> type as shown below

var ptpDocCount = ((Nest.SingleBucketAggregate)response.Aggregations["ptp_aggs"]).DocCount;
var bptpDocCount = ((Nest.SingleBucketAggregate)response.Aggregations["bptp_aggs"]).DocCount;

添加关键字搜索方法

QueryContainer qc1 = new QueryContainerDescriptor<TestReportModel>()
    .Bool(b => b.Must(m => m.Terms(t => t.Field(f => f.lastdispositioncode.Suffix("keyword"))
        .Terms(new string[]{"ptp"}))));

QueryContainer qc2 = new QueryContainerDescriptor<TestReportModel>()
    .Bool(b => b.Must(m => m.Terms(t => t.Field(f => f.lastdispositioncode.Suffix("keyword"))
        .Terms(new string[]{"bptp", "sbptp"}))));

现在可以将这些查询容器挂接到您的聚合中,如下所示

Now these query containers can be hooked to your aggregation as shown below

.Aggregations(aggs => aggs
    .Filter("f1", f => f.Filter(f => qc1))
    .Filter("f2", f => f.Filter(f => qc2)))

在这种情况下,由 NEST 客户端生成的聚合查询如下所示:

The queries for aggregations that are generated by the NEST client in this case look like below

"f1": {
      "filter": {
        "bool": {
          "must": [
            {
              "terms": {
                "lastdispositioncode.keyword": [
                  "bptp"
                ]
              }
            }
          ]
        }
      }
    }

此外,回到搜索不区分大小写的情况,Elasticsearch以不区分大小写的方式处理搜索.但是,它取决于分析的字段与未分析的字段.默认情况下,对分析字段进行标记化,对文本字段进行标记化.我们理想地在分析字段上使用 NEST 后缀扩展方法,并在分析字段上获得精确匹配.关于它们的更多信息此处

Also, coming back to the case of search being case-insensitive, Elasticsearch deals with search in a case-insensitive fashion. However, it varies depending on analyzed vs non-analyzed fields. Analyzed fields are tokenized and text fields are by default tokenized. We use the suffix extension method of NEST on analyzed fields ideally and to get an exact match on the analyzed field. More about them here

这篇关于如何使用NEST进行过滤器聚合?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆