Jacob Eckel
Jacob Eckel

Reputation: 1641

Elasticsearch: How to query or aggregate on multi-value field counts

I have to index email messages, each having a list of recipients, like this:

{
"To":[{"name":"John", "email":"[email protected]"}, {"name":"Jane", "email":"[email protected]"}],
"Body": "Blah blah blah"
}

I want to search in the body texts and perform aggregations over messages that have more than one recipient only. I tried to use token_count datatype and value_count aggregation, but neither seems to be applicable. Is there a way to define a filter over multi-value counter?

Upvotes: 2

Views: 817

Answers (2)

alpert
alpert

Reputation: 4655

Maybe a Script Query can work for you:

"bool" : {
    "must" : {
        // query on body
        ...
    },
    "filter" : {
        "script" : {
            "script" : {
                "inline" : "doc['To.name'].size() > param1"
                "params" : {
                    "param1" : 1
                }
            }
        }
    }
}

But dont forget to enable scripting: https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-scripting.html#enable-dynamic-scripting

Upvotes: 0

Andrei Stefan
Andrei Stefan

Reputation: 52368

Actually, I guess your To field is a nested field. I don't see why shouldn't be like that if you want to really associate a name with an email address. Otherwise it would just be a list of names and a list of addresses without any association between them.

If your field is a nested one then its mapping should be this one:

    "To": {
      "type": "nested",
      "include_in_parent": true, 
      "properties": {
        "name": {
          "type": "string"
        },
        "email": {
          "type": "string"
        }
      }
    }

Then the query to search for a certain number of email addresses:

{
  "query": {
    "bool": {
      "must": [
        {
          "match_all": {}
        }
      ],
      "filter": {
        "script": {
          "script": {
            "inline": "doc['To.name'].size() > counter",
            "params": {
              "counter": 1
            }
          }
        }
      }
    }
  }
}

Even if the field is not nested the query above still applies.

Upvotes: 1

Related Questions