简体   繁体   English

如何使用 NEST 进行过滤聚合?

[英]How to make Filter Aggregations using NEST?

I have a requirement for filter aggregations using NEST.我需要使用 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 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; }
    
}

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 访问弹性搜索,并且聚合/过滤器的 rest 是使用 Lambda 完成的。

I would like to perform the entire operation (Aggregations /Filter etc) using NEST framework and put it in the TestModel using filter aggregation.我想使用 NEST 框架执行整个操作(聚合/过滤器等),并使用过滤器聚合将其放入 TestModel 中。

How can I construct the DSL query inside NEST?如何在 NEST 中构建 DSL 查询?

Update更新

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))

                        )
               );

Result结果

在此处输入图像描述

I see that you are trying to perform a search on the type of TestReportModel .我看到您正在尝试对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.但是,附加到过滤器容器的查询存在问题。

Your TestReportModel contains two properties trialStatus and lastdispositioncode .您的TestReportModel包含两个属性trialStatuslastdispositioncode You are setting the Field property as description inside your terms query.您正在将Field属性设置为您的terms查询中的描述 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.您正在执行搜索的 model(反过来,您正在执行搜索的索引)没有属性description ,因此没有区别。 NEST or Elasticsearch, in this case does not throw any exception. NEST或 Elasticsearch,在这种情况下不会抛出任何异常。 Instead, it returns count zero.相反,它返回计数为零。 Field value should be modified to lastdispositioncode . Field值应修改为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; }        
}

Modified terms queries are as follows修饰terms查询如下

// 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" },
};

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.由于似乎lastdispositioncode的值似乎采用单个单词值(您的示例中的 PTP 或 BPTP),我相信,是否分析文档中的字段并不重要。 You can further obtain the counts from the ISearchResponse<T> type as shown below您可以进一步从ISearchResponse<T>类型中获取计数,如下所示

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

Edit: Adding an approach for keyword search编辑:添加关键字搜索的方法

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)))

The queries for aggregations that are generated by the NEST client in this case look like below在这种情况下, NEST客户端生成的聚合查询如下所示

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

Also, coming back to the case of search being case-insensitive, Elasticsearch deals with search in a case-insensitive fashion.此外,回到搜索不区分大小写的情况,Elasticsearch 以不区分大小写的方式处理搜索。 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.我们理想地在分析字段上使用NESTsuffix扩展方法,并在分析字段上获得精确匹配。 More about them here更多关于他们在这里

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM