title: Wrong results in elasticsearch complex boolean query over nested objects
body: <p>I have a recipients index containing a nested activity object which stores event types and campaign ids. </p>
  
  <p>Here is an example:</p>
  
  <pre><code>{
      email: 'm1@example.com',
      userId: 'user-id'
      listId: 'list-id'
      campaignActivity: [
         { event: 'received', campaignId: 'c1', timestamp: 1 },
         { event: 'received', campaignId: 'c3', timestamp: 3 }
      ]
  }
  </code></pre>
  
  <p>Here is my current mapping:</p>
  
  <pre><code>{
    "recipients_index_test": {
      "mappings": {
        "recipients": {
          "properties": {
            "campaignActivity": {
              "type": "nested",
              "properties": {
                "campaignId": {
                  "type": "text",
                  "fields": {
                    "keyword": {
                      "type": "keyword",
                      "ignore_above": 256
                    }
                  }
                },
                "event": {
                  "type": "text",
                  "fields": {
                    "keyword": {
                      "type": "keyword",
                      "ignore_above": 256
                    }
                  }
                },
                "timestamp": {
                  "type": "long"
                }
              }
            },
            "email": {
              "type": "text",
              "fields": {
                "keyword": {
                  "type": "keyword",
                  "ignore_above": 256
                }
              }
            },
            "id": {
              "type": "text",
              "fields": {
                "keyword": {
                  "type": "keyword",
                  "ignore_above": 256
                }
              }
            },
            "listId": {
              "type": "text",
              "fields": {
                "keyword": {
                  "type": "keyword",
                  "ignore_above": 256
                }
              }
            },
            "userId": {
              "type": "text",
              "fields": {
                "keyword": {
                  "type": "keyword",
                  "ignore_above": 256
                }
              }
            }
          }
        }
      }
    }
  }
  </code></pre>
  
  <p>Here is the sample data: </p>
  
  <pre><code>{
    email: 'nm1@example.com',
    userId: 'user-id',
    listId: 'list-id',
    campaignActivity: [
      { event: 'received', campaignId: 'c1', timestamp: 1 },
      { event: 'received', campaignId: 'c2', timestamp: 2 },
      { event: 'received', campaignId: 'c3', timestamp: 3 },
      { event: 'received', campaignId: 'c4', timestamp: 4 }
    ]
  },
  {
    email: 'nm2@example.com',
    userId: 'user-id',
    listId: 'list-id',
    campaignActivity: [
      { event: 'received', campaignId: 'c1', timestamp: 1 }
    ]
  },
  {
    email: 'm1@example.com',
    userId: 'user-id',
    listId: 'list-id',
    campaignActivity: []
  },
  {
    email: 'm2@example.com',
    userId: 'user-id',
    listId: 'list-id',
    campaignActivity: [
      { event: 'received', campaignId: 'c1', timestamp: 1 },
      { event: 'received', campaignId: 'c3', timestamp: 3 }
    ]
  },
  {
    email: 'm3@example.com',
    userId: 'user-id',
    listId: 'list-id',
    campaignActivity: [
      { event: 'received', campaignId: 'c2', timestamp: 2 },
      { event: 'received', campaignId: 'c3', timestamp: 3 }
    ]
  }
  </code></pre>
  
  <p>I want to get recipients who didn't receive some of c2, c3 or c4 campaigns (by excluding recipients who received all campaigns c2, c3 and c4) This is what I've been trying without luck:</p>
  
  <pre><code>{
    "query": {
      "bool": {
        "must_not": [
          {
            "nested": {
              "path": "campaignActivity",
              "query": {
                "bool": {
                  "filter": [
                    {
                      "term": {
                        "campaignActivity.campaignId.keyword": "c4"
                      }
                    },
                    {
                      "term": {
                        "campaignActivity.event.keyword": "received"
                      }
                    }
                  ]
                }
              }
            }
          },
          {
            "nested": {
              "path": "campaignActivity",
              "query": {
                "bool": {
                  "filter": [
                    {
                      "term": {
                        "campaignActivity.campaignId.keyword": "c3"
                      }
                    },
                    {
                      "term": {
                        "campaignActivity.event.keyword": "received"
                      }
                    }
                  ]
                }
              }
            }
          },
          {
            "nested": {
              "path": "campaignActivity",
              "query": {
                "bool": {
                  "filter": [
                    {
                      "term": {
                        "campaignActivity.campaignId.keyword": "c2"
                      }
                    },
                    {
                      "term": {
                        "campaignActivity.event.keyword": "received"
                      }
                    }
                  ]
                }
              }
            }
          }
        ]
      }
    },
    "from": 0,
    "size": 10
  }
  </code></pre>
  
  <p>Above query returns nm2@example.com and m1@example.com but I'm looking for a result with m1@example.com, m2@example.com, and m3@example.com</p>
  
  <p>What am I doing wrong?</p>
  
  <p><strong>UPDATE 1:</strong></p>
  
  <p>This is the closest I've gotten so far:</p>
  
  <pre><code>{
    "query": {
      "bool": {
        "filter": [
          {
            "nested": {
              "path": "campaignActivity",
              "query": {
                "bool": {
                  "filter": [
                    {
                      "term": {
                        "campaignActivity.event.keyword": "received"
                      }
                    },
                    {
                      "terms": {
                        "campaignActivity.campaignId.keyword": [
                          "c4",
                          "c3",
                          "c2"
                        ]
                      }
                    }
                  ]
                }
              }
            }
          }
        ],
        "should": [
          {
            "nested": {
              "path": "campaignActivity",
              "query": {
                "bool": {
                  "must_not": [
                    {
                      "term": {
                        "campaignActivity.campaignId.keyword": "c4"
                      }
                    },
                    {
                      "term": {
                        "campaignActivity.event.keyword": "received"
                      }
                    }
                  ]
                }
              }
            }
          },
          {
            "nested": {
              "path": "campaignActivity",
              "query": {
                "bool": {
                  "must_not": [
                    {
                      "term": {
                        "campaignActivity.campaignId.keyword": "c3"
                      }
                    },
                    {
                      "term": {
                        "campaignActivity.event.keyword": "received"
                      }
                    }
                  ]
                }
              }
            }
          },
          {
            "nested": {
              "path": "campaignActivity",
              "query": {
                "bool": {
                  "must_not": [
                    {
                      "term": {
                        "campaignActivity.campaignId.keyword": "c2"
                      }
                    },
                    {
                      "term": {
                        "campaignActivity.event.keyword": "received"
                      }
                    }
                  ]
                }
              }
            }
          }
        ]
      }
    },
    "from": 0,
    "size": 10
  }
  </code></pre>
  
  <p>But it still returns nm1@example.com which shouldn't be part of the result because it received all of the campaigns (c2,c3,c4) and is missing m1@example.com.</p>