Matt Hintzke
Matt Hintzke

Reputation: 7994

Multi-term filter in ElasticSearch (NEST)

I am trying to query documents based on a given field having multiple possible values. For example, my documents have an "extension" property which is the extension type of a file like .docx, xls, .pdf, etc. I want to be able to filter my "extensions" property on any number of values, but cannot find the correct syntax needed to get this functionality. Here is my current query:

desc.Type("entity")
                .Routing(serviceId)
                .From(pageSize * pageOffset)
                .Size(pageSize)
                .Query(q => q
                    .Filtered(f => f
                        .Query(qq =>
                            qq.MultiMatch(m => m
                                .Query(query)
                                .OnFields(_searchFields)) ||
                            qq.Prefix(p1 => p1
                                .OnField("entityName")
                                .Value(query)) ||
                            qq.Prefix(p2 => p2
                                .OnField("friendlyUrl")
                                .Value(query))
                        )
                        .Filter(ff =>
                            ff.Term("serviceId", serviceId) &&
                            ff.Term("subscriptionId", subscriptionId) &&
                            ff.Term("subscriptionType", subscriptionType) &&
                            ff.Term("entityType", entityType)
                        )
                    )
                );

P.S. It may be easier to think of it in the inverse, where I send up the file extensions I DON'T want and set up the query to get documents that DON'T have any of the extension values given.

Upvotes: 3

Views: 1964

Answers (2)

jhilden
jhilden

Reputation: 12429

If you want to return items that match ".doc" OR ".xls" then you want a TERMS query. Here is a sample:

        var searchResult = ElasticClient
            .Search<SomeESType>(s => s
                .Query(q => q
                    .Filtered(fq => fq
                        .Filter(f => f
                            .Terms(t => t.Field123, new List<string> {".doc", ".xls"})
                        )
                    )
                )
            )

Upvotes: 2

Evaldas Buinauskas
Evaldas Buinauskas

Reputation: 14077

After discussion, this should be a raw json query, that should work and can be translated to NEST quite easily:

POST /test/_search
{
  "query": {
    "filtered": {
      "query": {
        "match_all": {}
      },
      "filter": {
        "bool": {
          "must": [
            {
              "term": {
                "serviceId": "VALUE"
              }
            },
            {
              "term": {
                "subscriptionId": "VALUE"
              }
            },
            {
              "term": {
                "subscriptionType": "VALUE"
              }
            },
            {
              "term": {
                "entityType": "VALUE"
              }
            }
          ],
          "must_not": [
            {
              "terms": {
                "extension": [
                  "docx",
                  "doc"
                ]
              }
            }
          ]
        }
      }
    }
  }
}

What had to be done:

In order to have clauses that have to exist and the ones, that need to be filtered out, bool query suited best.

  • Must query stores all clauses that are present in OPs query
  • Must_not query should store all extensions that need to be filtered out

Upvotes: 2

Related Questions