错误导致弹性搜索对嵌套对象的复杂布尔查询

时间:2018-05-21 13:35:00

标签: elasticsearch

我有一个收件人索引,其中包含一个存储事件类型和活动ID的嵌套活动对象。

以下是一个例子:

{
    email: 'm1@example.com',
    userId: 'user-id'
    listId: 'list-id'
    campaignActivity: [
       { event: 'received', campaignId: 'c1', timestamp: 1 },
       { event: 'received', campaignId: 'c3', timestamp: 3 }
    ]
}

这是我目前的映射:

{
  "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
              }
            }
          }
        }
      }
    }
  }
}

以下是示例数据:

{
  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 }
  ]
}

我想收到没有收到某些c2,c3或c4广告系列的收件人(通过排除收到所有广告系列c2,c3和c4的收件人)这就是我一直没有运气的尝试:

{
  "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
}

以上查询返回nm2@example.com和m1@example.com但我正在寻找m1 @ example.com,m2 @ example.com和m3@example.com的结果

我做错了什么?

更新1:

这是我到目前为止最接近的:

{
  "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
}

但它仍会返回nm1@example.com,因为它收到了所有广告系列(c2,c3,c4)并且缺少m1@example.com,因此不应该成为结果的一部分。

1 个答案:

答案 0 :(得分:0)

我设法让它使用此查询:

{
  "query": {
    "bool": {
      "must": [
        {
          "bool": {
            "should": [
              {
                "bool": {
                  "must_not": [
                    {
                      "nested": {
                        "path": "campaignActivity",
                        "query": {
                          "bool": {
                            "filter": {
                              "exists": {
                                "field": "campaignActivity"
                              }
                            }
                          }
                        }
                      }
                    }
                  ]
                }
              },
              {
                //match c2
              },
              {
                //match c3
              },
              {
                //match c4
              }
            ]
          }
        },
        {
          "bool": {
            "must_not": [
              {
                "bool": {
                  "must": [
                    {
                      //match c2
                    },
                    {
                      //match c3
                    },
                    {
                      //match c4
                    }
                  ]
                }
              }
            ]
          }
        }
      ]
    }
  }
}

我希望将来对某人有所帮助。