TermsQuery class in elastic.clients.elasticsearch (8.x)

In a .NET app, I am migrating from NEST (7.x) to Elastic.Clients.Elasticsearch (8.x). In NEST, I am dynamically building a List<QueryContainer> called queries. One section determines the need of a Terms query and if so, it is doing this where values is a string[] of values:

queries.Add(new TermsQuery
{
    Field = kvp.Key.ToSnakeCase(),
    Terms = values
});

The problem with (8.x) is that Terms is no longer a property of TermsQuery class.

Any suggestions or alternatives for how to do this in 8.x lib?

Hi @moyerskd,

it should work with:

new TermsQuery
{
  // ...
  Term = new TermsQueryField(values)
}

Hi, and thank you for the reply. I have tried that, but TermsQueryField only takes a readonly collection of FieldValue. The values I'm trying to use are string[]. Is there some other way?

Thanks!

Can it be done like this?

var terms = new ReadOnlyCollection<FieldValue>(new List<FieldValue>
{
    "some value"
});
queries.Add(new TermsQuery
{
    Field = kvp.Key,
    Term = new TermsQueryField(terms)
});

Also, in NEST, we were able to create a "must_not" by doing this. With the bang in front of the new TermsQuery.

queries.Add(!new TermQuery(kvp.Key.ToSnakeCase())
{
    Field = kvp.Key.ToSnakeCase(),
    Terms = values

});

It doesn't allow this in 8.x. Is there an equivalent to that process?

Thanks!

Hi @moyerskd,

FieldValue can be constructed from string, so you might want to cast it before passing it to the TermsQueryField constructor:

new TermsQueryField(values.Select(x => (FieldValue)x))

This does as well work, yes!

This feature is currently not implemented yet. In the meantime you have to use the verbose query like this:

.Bool(b => b
    .MustNot(q => q
        .Term(t => ...)
    )
)

Thank you! Your help has been invaluable. If you wouldn't mind, will you assist with this one? Below the SearchDescriptor<T> and IPromise<> are old concepts in NEST. What are the equivalents to these in 8.x? Also, how to use the CountDescriptor<>?

Thanks!

NEST:

Func<SearchDescriptor<T>, Elastic.Clients.Elasticsearch.SearchRequest> search = (s) =>
{
    var r = s.Query(q => q.QueryString(d => d.Query(query))).Size(pagingInfo.Size);

    if (!string.IsNullOrEmpty(pit) && pagingInfo.Enabled)
    {
        Logger.LogDebug("Point in time included on search of index '{Index}'", indexName);
        s.PointInTime(pit);
    }
    else
    {
        s.Index(index);
    }

    if (pagingInfo.SortFilters == null || !pagingInfo.SortFilters.Any())
    {
        pagingInfo.SortFilters = new Dictionary<string, bool> { { "id", true } };
    }

    s.Sort((sort) =>
    {
        return (IPromise<IList<ISort>>)CreateSort(pagingInfo.SortFilters);
    });

    if (afterKeys?.Count > 0)
    {
        Logger.LogDebug("Search after included on search of index '{Index}'", indexName);
        s.SearchAfter(ScrubPagingAfterKeys(afterKeys));
    }

    return r;
};