Search code examples
c#elasticsearchnest

How to define TermsQuery for searching list of integer?


Using the object initializer syntax, on the line that define the Terms, I am getting an error: Cannot convert source type 'System.Collections.Generic.List<int>' to target type 'System.Collections.Generic.IEnumerable<object>'

var query = new TermsQuery
{
 Field = new Field("seq"),
 Terms = new List<int> {1 ,2, 3}
};

This works if define using fluent DSL

var search = new List<int> {1, 2, 3};   

q.Terms(c => c
    .Field(p => p.seq)
    .Terms(search)
)

What are I doing wrong with the object initializer syntax? Thanks for any help in advance.


Solution

  • I can attribute the failure in the first case to a fundamental point of C#. int is a value type and trying to assign a List<int> to IEnumerable<object> fails because generic variance is not supported for value types. The same thing works fine if you assign a List<string> to the IEnumerable<object> reference type. Take a look at this answer by Jon Skeet to understand more on this. Additionally, you can look up more on the Covariance and Contravariance in generics from MSDN. One way to get this working is performing an explicit cast on your List<int> type variable.

    Further, for the case of fluent DSL approach, there are two overloads that are possible for the Terms method.

    TermsQueryDescriptor<T> Terms<TValue>(IEnumerable<TValue> terms)
    

    and

    TermsQueryDescriptor<T> Terms<TValue>(params TValue[] terms)
    

    If you take a look at the implementation of these methods from here, you would see that the type T that is being passed in is inferred and the required casting is done internally. That is why you wouldn't face this issue in the case of fluent DSL approach.