Using NEST how can I build up a search query

I am trying to use the NEST APIs to execute a search. In my logic of building this up with the fluent api I need to do a conditional check and so far I have this however I believe my assignment will be getting overwritten. Is there a recommended way to do this type of thing?

   var d = new SearchDescriptor<AuditLog>();
                d = d.Query(q => q
                    .Bool(b => b
                        .Filter(bf => bf
                            .DateRange(r => r
                                .Field(f => f.UtcDateTime)
                                .GreaterThanOrEquals(message.UtcFrom)
                                .LessThanOrEquals(message.UtcTo)
                            )
                        ).Filter(fg => fg.Terms(descriptor => descriptor.Field(f => f.AccessControlid).Terms(aclIds)))
                    )
                );


                if (message.CustomerId != -1)
                {
                    d = d.Query(q => q.Bool(kk => kk.Must(must => must.Match(m => m.Field(c => c.AuditUserId).Query("2")))));
                }
                
               
                var resp = this.elasticClient.Search<AuditLog>(s =>
                {
                    s = d;
                    return s
                        .Index(ElasticIndex.AuditLog)
                        .Size(20)
                        .From(message.Offset);
                });

Ended up using this which seems to work. No idea if it's the correct way though.

                Func<QueryContainerDescriptor<AuditLog>, QueryContainer> dateRangeSearch = descriptor => descriptor.DateRange(r => r
                    .Field(f => f.UtcDateTime)
                    .GreaterThanOrEquals(message.UtcFrom)
                    .LessThanOrEquals(message.UtcTo)
                );

                Func<QueryContainerDescriptor<AuditLog>, QueryContainer> aclSearch = descriptor => descriptor.Terms(r => r.Field(f => f.AccessControlid).Terms(aclIds));

                Func<QueryContainerDescriptor<AuditLog>, QueryContainer> customerSearch = descriptor => descriptor.Terms(r => r.Field(f => f.AuditUserId).Terms(userIds));

                var searchTerms = new List<Func<QueryContainerDescriptor<AuditLog>, QueryContainer>> { dateRangeSearch, aclSearch };

                if (message.CustomerId != -1)
                {
                    searchTerms.Add(customerSearch);
                }

                var resp = this.elasticClient.Search<AuditLog>(s =>
                {
                    return s
                        .Query(q => q.Bool(b => b.Filter(searchTerms)))
                        .Index(ElasticIndex.AuditLog)
                        .Size(20)
                        .From(message.Offset);
                });

Your query looks fine. Pretty much all NEST fluent API calls are assignative, so last assignment wins. I think may be one or two places in the API where a call is additive, but this should be considered a bug.

With query operator overloading, the code could be made more succinct with

resp = client.Search<AuditLog>(s => s
	.Query(q =>
	{
		QueryContainer c = +q.DateRange(r => r
				.Field(f => f.UtcDateTime)
				.GreaterThanOrEquals(message.UtcFrom)
				.LessThanOrEquals(message.UtcTo)
			) && 
			+q.Terms(r => r.Field(f => f.AccessControlid).Terms(aclIds));

		if (message.CustomerId != -1)
			c = c && +q.Terms(r => r.Field(f => f.AuditUserId).Terms(userIds));

		return c;
	})
	.Index("audit_log")
	.Size(20)
	.From(message.Offset)
);

This takes advantage of unary + operator overloading to specify a bool query filter clause, and combining them with binary && operator.

With the following

var now = DateTime.UtcNow;
var message = new Message
{
	CustomerId = 10,
	UtcFrom = now.AddMonths(-1),
	UtcTo = now,
};

var aclIds = new []{"acl1", "acl2"};
var userIds = new []{"user1", "user2"};

both produce

POST http://localhost:9200/audit_log/auditlog/_search
{
  "from": 0,
  "size": 20,
  "query": {
    "bool": {
      "filter": [
        {
          "range": {
            "utcDateTime": {
              "gte": "2018-02-23T00:30:10.019915Z",
              "lte": "2018-03-23T00:30:10.019915Z"
            }
          }
        },
        {
          "terms": {
            "accessControlid": [
              "acl1",
              "acl2"
            ]
          }
        },
        {
          "terms": {
            "auditUserId": [
              "user1",
              "user2"
            ]
          }
        }
      ]
    }
  }
}

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.