I have an ElasticSearch server that I want to query. I want to replicate the behavior of in
operator in a SQL server using the NEST library.
Here is a short version of the Product
class which is what I am using to search where the Type
field is in request.Types
public class Product
{
[Text(Name = "types")]
public string[] Types { get; set; }
[Text(Name = "price")]
public double Price { get; set; }
// ...
}
Here is my query request using the Nest library
var properties = await client.SearchAsync<Product>(x =>
{
x = x.Query(q =>
{
if (request.MinPrice.HasValue || request.MaxPrice.HasValue)
{
q.Range(r =>
{
if (request.MinPrice.HasValue)
{
r = r.Field(x => x.Price).GreaterThanOrEquals((double)request.MinPrice.Value);
}
if (request.MaxPrice.HasValue)
{
r = r.Field(x => x.Price).LessThanOrEquals((double)request.MaxPrice.Value);
}
return r;
});
}
if (request.Types != null && request.Types.Length > 0)
{
// Here I need to query the Type field where field in request.Types
}
return q;
});
return x;
});
As you can see in the comment above, I want to add the "in clause" only when the request.Types
has value and the server has at least one matching type.
How can I add in clause
condition?
I can see two possible interpretations of the requirement:
query documents that have Types
that intersect with request.Types
A terms query can achieve this. Typically, a terms query targets a field mapped as a keyword
type, but Product.Types
is mapped as a text
type. You may want to consider changing the mapping to map as keyword
, or map it as both text
and keyword
with a multi-field.
With Product.Types
mapped as a keyword
type, the query would be
q.Terms(t => t
.Field(f => f.Types)
.Terms(request.Types)
);
query documents that have all the exact Types
specified in request.Types
A terms set query can achieve this. As before, the Types
field should be mapped as a keyword
, then the query would be
q.TermsSet(t => t
.Field(f => f.Types)
.Terms(request.Types)
.MinimumShouldMatchScript(s => s
.Source("params.request_types_len")
.Params(d => d
.Add("request_types_len", request.Types.Length)
)
)
);