Sameer Deshmukh
Sameer Deshmukh

Reputation: 1379

ElasticSearch - NEST - how to combine AND and OR statements

I am new to ElasticSearch - NEST API.

We are trying to prepare multiple conditions with AND/OR clauses. For example - (Condition 1 OR Condition 2) AND (Condition 3)

Currently we are trying by concatenating the query conditions.

Can anyone provide the better example using NEST API?

Upvotes: 3

Views: 7371

Answers (2)

Utsav Dawn
Utsav Dawn

Reputation: 8246

Well there is something called Bool Query in ElasticSearch. A query that matches documents matching boolean combinations (AND, OR, NOT) of other queries. It is built using one or more boolean clauses, each clause with a typed occurrence. The occurrence types are:

must: (AND)The clause (query) must appear in matching documents.

should: (OR) The clause (query) should appear in the matching document. In a boolean query with no must clauses, one or more should clauses must match a document. The minimum number of should clauses to match can be set using the minimum_should_match parameter.

must_not: (NOT) The clause (query) must not appear in the matching documents.

So for the example you have given, you will get the following query:

bool 
    should
        condition 1
        condition 2
    bool
        must
            condition 3

And in ElasticSearch the code will look like:

"filter": {
           "bool": {
               "should": [
                             {"term": {"tag": value1}},
                             {"term": {"tag": value2}}
                         ],
                         "bool": {
                                 "must":{"term": {"tag": "value3"}}
                                 }
                    }
           }

And in NEST it will look like:

Filter(f=>f
   .Bool(b=>b
       .Should(
          o=>o.Term(t=>t.Tag, Value1),
          o=>o.Term(t=>t.Tag, Value2)),
          o=>o.Bool(bo=>bo
            .Must(a=>a.Term(t=>t.Tag, Value3))
        )
    )
)

According to the NEST documentation instead of writing such tedious and verbose queries you can use NEST's Bitwise operators, which is simple.

.Query((q=>q.Term(tag, value1) || q.Term(tag, value2)) && q.Term(tag, value3))

Upvotes: 6

jhilden
jhilden

Reputation: 12419

Here is the raw data setup and query:

PUT hilden1

POST hilden1/type1
{
  "f1": 123,
  "f2": 456,
  "f3": 789
}

GET hilden1/type1/_search
{
  "query": {
    "filtered": {
      "filter": {
        "and": {
          "filters": [
            {
              "term": {
                "f1": "123"
              }
            },
            {
              "or": {
                "filters": [
                  {
                    "term": {
                      "f2": "456"
                    }
                  },
                  {
                    "term": {
                      "f3": "888"
                    }
                  }
                ]
              }
            }
          ]
        }
      }
    }
  }
}

Here is the rough nest equivalent:

    var search = ElasticClient.Search<AuthForReporting>(s=> s
        .Query(q=> q
            .Filtered(fq => fq
                .Filter(f=> f
                    .And(
                        a=> a.Term(t=> t.f1, 123),
                        a => a.Or(
                            o => o.Term(t=>t.f2, 456),
                            o => o.Term(t => t.f3, 888)
                            )
                    )
                )
            )
        )
        );

Upvotes: 0

Related Questions