elasticsearchnest

Elasticsearch NEST 5.x Search Query that is built dynamically


I have the following query that I build piecemeal/dynamically using "&=". Elasticsearch 5.x and Nest 5.x.

QueryContainer qfilter = null;

qfilter = Query<ClassEL>.Term(m => m.OrderID, iOrderID);

qfilter &= Query<ClassEL>
.Range(r => r
  .Field(f => f.Distance)
  .GreaterThan(100))
&&
.Query<ClassEL>.Term(t => t.Active, true);

 var searchDes = new SearchDescriptor<ClassEL>()
 .From(0)
 .Size(10)
 .Query(qfilter);  <===== *** ERROR HERE ***

In Visual Studio, it shows the following error message tip:

Error: Cannot convert from 'Nest.QueryContainer' to 'System.Func<Nest.QueryContainerDescriptor<ClassEL>, Nest.QueryContainer>'

The problem is I can't get the searchDescriptor to accept the query I built. Examples online show Search + Query rolled into one which differs from what I'm trying to accomplish. Below is common example that I want to avoid:

var response = client.Search<Tweet>(s => s
    .From(0)
    .Size(10)
    .Query(q =>
            q.Term(t => t.User, "kimchy")
            || q.Match(mq => mq.Field(f => f.User).Query("nest"))
        )
    );

EDIT: Using the Andrey's answer works just fine. A problem arises however when I try to get the results back from the search query:

List<ClassViewEL> listDocuments = response.Documents.ToList();

Visual Studio doesn't highlight it as an error immediately, but during compile time has a problem:

error CS0570: 'Nest.ISearchResponse<Website.Common.BizServiceViewEL>.Documents' is not supported by the language

Debugging and choosing to IGNORE the above error works fine, the code executes just as expected no problems. However the compile time error will prevent code deployments. How can this error be fixed?

Solution to EDIT: One of my dependencies in my projects (Newtonsoft.Json.dll) were targeting an older version causing the error to appear. Cleaning the solution and rebuilding fixes it.


Solution

  • You should use Func<SearchDescriptor<ClassEL>, ISearchRequest> or pass descriptor in separate method. For example:

    var queryContainer = Query<ClassEL>.Term(x => x.Field(f => f.FirstName).Value("FirstName"));
    queryContainer &= Query<ClassEL>.Term(x => x.Field(f => f.LastName).Value("LastName"));
    
    Func<SearchDescriptor<ClassEL>, ISearchRequest> searchFunc = searchDescriptor => searchDescriptor
                                                                                            .Index("indexName")
                                                                                            .Query(q => queryContainer);
    
    var response = _client.Search<ClassEL>(searchFunc);
    

    or like this

    ISearchRequest ExecuteQuery(SearchDescriptor<ClassEL> searchDescriptor, QueryContainer queryContainer)
    {
        return searchDescriptor.Index("indexName")
            .Query(q => queryContainer);
    }
    
    public void GetResults()
    {
        var queryContainer = Query<ClassEL>.Term(x => x.Field(f => f.FirstName).Value("FirstName"));
        queryContainer &= Query<ClassEL>.Term(x => x.Field(f => f.LastName).Value("LastName"));
    
        var response = _client.Search<ClassEL>(s => ExecuteQuery(s, queryContainer));
    }