Reputation: 376
So, this is my query:
_elasticClient.Search<SearchItem>(x =>
x.Sort(sort).Size(itemsPerPage)
.Query(q =>
q.MultiMatch(m => m
.Fields(fs => fs
.Field(p => p.Field1)
.Field(p => p.Field2)
.Field(p => p.Field3)
.Field(p => p.Field4)
.Field(p => p.Field5)
.Field(p => p.Field6)
)
.Operator(Operator.And)
.Query(pattern)
)));
I have to apply different filters. Range filters (for price), filter result set where field1 = "Audi" and field2 = "Sale Car". I tried to do something like that:
.Query(q =>
q.MultiMatch(m => m
.Fields(fs => fs
Field(p => p.Field1)
.Field(p => p.Field2)
.Field(p => p.Field3)
.Field(p => p.Field4)
.Field(p => p.Field5)
.Field(p => p.Field6)
)
.Operator(Operator.And)
.Query(pattern)))
.Query(q=>q.Range(ra=>ra.Field(ff=>ff.SalePrice).GreaterThan(1000))));
But this is not working. I've all results from the index with price greater then 1000, but need only searched results. Could anyone help me?
Upvotes: 0
Views: 5588
Reputation: 125518
You can use a bool
query to combine queries and NEST makes this slightly easier to work with by overloading operators to combine QueryContainer
s (the root query type). Here's an example for NEST 2.x
void Main()
{
var connectionPool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
var settings = new ConnectionSettings(connectionPool);
var client = new ElasticClient(settings);
var itemsPerPage = 20;
var pattern = "match query";
client.Search<SearchItem>(x => x
.Sort(so => so
.Descending("_score")
)
.Size(itemsPerPage)
.Query(q => q
.MultiMatch(m => m
.Fields(fs => fs
.Field(p => p.Field1)
.Field(p => p.Field2)
.Field(p => p.Field3)
.Field(p => p.Field4)
.Field(p => p.Field5)
.Field(p => p.Field6)
)
.Operator(Operator.And)
.Query(pattern)
) && q
.Range(ra => ra
.Field(ff=>ff.SalePrice)
.GreaterThan(1000)
)
)
);
}
public class SearchItem
{
public int SalePrice { get; set; }
public string Field1 { get; set; }
public string Field2 { get; set; }
public string Field3 { get; set; }
public string Field4 { get; set; }
public string Field5 { get; set; }
public string Field6 { get; set; }
}
which yields
{
"size": 20,
"sort": [
{
"_score": {
"order": "desc"
}
}
],
"query": {
"bool": {
"must": [
{
"multi_match": {
"query": "match query",
"operator": "and",
"fields": [
"field1",
"field2",
"field3",
"field4",
"field5",
"field6"
]
}
},
{
"range": {
"salePrice": {
"gt": 1000.0
}
}
}
]
}
}
}
This will find documents that are a match for the multi_match
query and also have a salePrice
greater than 1000. Since we don't need a score calculated for the range query (a document either has a salePrice
greater than 1000 or it doesn't), the range query can run in a filter context. A slightly refined version
client.Search<SearchItem>(x => x
.Sort(so => so
.Descending("_score")
)
.Size(itemsPerPage)
.Query(q => q
.MultiMatch(m => m
.Fields(fs => fs
.Field(p => p.Field1)
.Field(p => p.Field2)
.Field(p => p.Field3)
.Field(p => p.Field4)
.Field(p => p.Field5)
.Field(p => p.Field6)
)
.Operator(Operator.And)
.Query(pattern)
) && +q
.Range(ra => ra
.Field(ff=>ff.SalePrice)
.GreaterThan(1000)
)
)
);
appending the unary +
operator to the range query is a shorthand for a bool query filter. The query json now looks like
{
"size": 20,
"sort": [
{
"_score": {
"order": "desc"
}
}
],
"query": {
"bool": {
"must": [
{
"multi_match": {
"query": "match query",
"operator": "and",
"fields": [
"field1",
"field2",
"field3",
"field4",
"field5",
"field6"
]
}
}
],
"filter": [
{
"range": {
"salePrice": {
"gt": 1000.0
}
}
}
]
}
}
}
Upvotes: 3