过滤器中的聚合仅返回所有已过滤文档中的值?

时间:2015-05-07 09:43:30

标签: elasticsearch e-commerce filtering faceted-search

对于电子商务过滤系统,必须在整个过滤集合中计算ElasticSearch中的聚合。

没有过滤器,我们得到:

"filters":{  
    "colour":{  
        "red":{  
            "count":5
        },
        "blue":{  
            "count":4
        }
    },
    "size":{  
        "L":{  
            "count":16
        },
        "M":{  
            "count":15
        }
    }
}

仅过滤红色,我们得到:

"filters":{  
    "colour":{  
        "red":{  
            "count":5
        },
        "blue":{  
            "count":3
        }
    },
    "size":{  
        "L":{  
            "count":1
        },
        "M":{  
            "count":1
        }
    }
}

仅在蓝色上过滤,我们得到:

"filters":{  
    "colour":{  
        "blue":{  
            "count":4
        },
        "red":{  
            "count":3
        }
    }
}

蓝色没有尺寸,没关系。但是,如果我们将两者结合起来:

"filters":{  
    "colour":{  
        "red":{  
            "count":5
        },
        "blue":{  
            "count":4
        }
    },
    "size":{  
        "L":{  
            "count":1
        },
        "M":{  
            "count":1
        }

根本不应返回尺寸,因为它与两种颜色都不匹配。

这是发送给ES的内容:

{  
    "size":1000,
    "fields":[  
        "id",
        "name",
        "price",
        "colour",
        "size"
    ],
    "query":{  
        "filtered":{  
            "query":{  
                "match_all":{}
            },
            "filter":{  
                "bool":{  
                    "must":[  
                        {  
                            "term":{  
                                "categories":4838
                            }
                        },
                        {  
                            "bool":{  
                                "should":[  
                                    {  
                                        "term":{  
                                            "colour":"blue"
                                        }
                                    },
                                    {  
                                        "term":{  
                                            "colour":"red"
                                        }
                                    }
                                ]
                            }
                        }
                    ]
                }
            }
        }
    },
    "aggs":{  
        "price":{  
            "stats":{  
                "field":"price"
            }
        },
        "discounted":{  
            "terms":{  
                "field":"discounted"
            }
        },
        "stock":{  
            "filter":{  
                "range":{  
                    "stock":{  
                        "gt":0
                    }
                }
            }
        },
        "colour":{  
            "terms":{  
                "field":"colour"
            }
        },
        "size":{  
            "terms":{  
                "field":"size"
            }
        }
    }
}

出了什么问题?如何设置仅在与所有文档匹配的已过滤子集上聚合?

1 个答案:

答案 0 :(得分:2)

结果与查询一致

{
  "bool": {
    "must": [{
      "term": {
        "categories": 4838
      }
    }, {
      "bool": {
        "should": [{
          "term": {
            "colour": "blue"
          }
        }, {
          "term": {
            "colour": "red"
          }
        }]
      }
    }]
  }
}

您要求的类别为4838,蓝色 OR 红色。当您对大小执行聚合时,会为数据集中的每个大小创建存储桶,其中包含类别4838的蓝色和红色项目。这就是您在结果中获得红色项目大小的原因。

  

如何设置仅在与所有文档匹配的已过滤子集上进行聚合?

我不确定您的问题,因为您的过滤子集包含红色和蓝色项目。您可以使用子聚合(https://www.elastic.co/blog/intro-to-aggregations-pt-2-sub-aggregations)在结果中按颜色显示大小

更新1:

  

如果选择蓝色和红色,M仅用于蓝色产品,但L用于红色和蓝色,我只想返回L

所以你希望尺寸取决于颜色

"aggs": {
  "price": {
    "stats": {
      "field": "price"
    }
  },
  "discounted": {
    "terms": {
      "field": "discounted"
    }
  },
  "stock": {
    "filter": {
      "range": {
        "stock": {
          "gt": 0
        }
      }
    }
  },
  "colour": {
    "terms": {
      "field": "colour"
    },
    "aggs": {
      "size": {
        "terms": {
          "field": "size"
        }
      }
    }
  }
}

您可以使用子聚合(https://www.elastic.co/blog/intro-to-aggregations-pt-2-sub-aggregations

更新2:

讨论后的最终答案,保留OR查询的结果,但只保留聚合中的AND查询结果

{
  "aggs": {
    "colorsizes": {
      "filters": {
        "filters": [{
          "bool": {
            "must": [{
              "term": {
                "size": "red"
              }
            }, {
              "term": {
                "size": "blue"
              }
            }]
          }
        }]
      },
      "aggs": {
        "size": {
          "terms": {
            "field": "size"
          }
        }
      }
    }
  }
}