title: Elasticsearch - generic facets structure - calculating aggregations combined with filters
body: <p>In a new project of ours, we were inspired by this article <a href="http://project-a.github.io/on-site-search-design-patterns-for-e-commerce/#generic-faceted-search" rel="noreferrer">http://project-a.github.io/on-site-search-design-patterns-for-e-commerce/#generic-faceted-search</a> for doing our “facet” structure. And while I have got it working to the extent the article describes, I have run into issues in getting it to work when selecting facets. I hope someone can give a hint as to something to try, so I don’t have to redo all our aggregations into separate aggregation calculations again.</p>
  
  <p>The problem is basically that we are using a single aggregation to calculate all the “facets” at once, but when I add a filter (fx. checking a brand name), then it “removes” all the other brands when returning the aggregates. What I basically want is that it should use that brand as filter when calculating the other facets, but not when calculating the brand aggregations. This is necessary so the user can, for example, choose multiple brands.</p>
  
  <p>Looking at <a href="https://www.contorion.de/search/Metabo_Fein/ou1-ou2?q=Winkelschleifer&amp;c=bovy" rel="noreferrer">https://www.contorion.de/search/Metabo_Fein/ou1-ou2?q=Winkelschleifer&amp;c=bovy</a> (which is the site described in the above article), I have selected the “Metabo” and “Fein” manufacturer (Hersteller), and unfolding the Hersteller menu it shows all manufacturers and not just the ones selected. So I know it’s possible somehow and I hope some one out there has a hint as to how to write the aggregations / filters, so I get the "correct e-commerce facet behavior".</p>
  
  <p>On the products in ES I have the following structure: (the same as in the original article, though “C#’ified” in naming)</p>
  
  <pre><code>"attributeStrings": [
      {
          "facetName": "Property",
          "facetValue": "Organic"
      },
      {
          "facetName": "Property",
          "facetValue": "Without parfume"
      },
      {
          "facetName": "Brand",
          "facetValue": "Adidas"
      }
  ]
  </code></pre>
  
  <p>So the above product has 2 attributes/facet groups – Property with 2 values (Organic, Without parfume) and Brand with 1 value (Adidas).
  Without any filters I calculate the aggregations from the following query:</p>
  
  <pre><code>  "aggs": {
      "agg_attr_strings_filter": {
        "filter": {},
        "aggs": {
          "agg_attr_strings": {
            "nested": {
              "path": "attributeStrings"
            },
            "aggs": {
              "attr_name": {
                "terms": {
                  "field": "attributeStrings.facetName"
                },
                "aggs": {
                  "attr_value": {
                    "terms": {
                      "field": "attributeStrings.facetValue",
                      "size": 1000,
                      "order": [
                        {
                          "_term": "asc"
                        }
                      ]
     } } } } } } } }
  </code></pre>
  
  <p>Now if I select Property "Organic" and Brand "Adidas" I build the same aggregation, but with a filter to apply those two constraints (which is were it kind of goes wrong...):</p>
  
  <pre><code>  "aggs": {
      "agg_attr_strings_filter": {
        "filter": {
          "bool": {
            "filter": [
              {
                "nested": {
                  "query": {
                    "bool": {
                      "filter": [
                        {
                          "term": {
                            "attributeStrings.facetName": {
                              "value": "Property"
                            }
                          }
                        },
                        {
                          "terms": {
                            "attributeStrings.facetValue": [
                              "Organic"
                            ]
                          }
                        }
                      ]
                    }
                  },
                  "path": "attributeStrings"
                }
              },
              {
                "nested": {
                  "query": {
                    "bool": {
                      "filter": [
                        {
                          "term": {
                            "attributeStrings.facetName": {
                              "value": "Brand"
                            }
                          }
                        },
                        {
                          "terms": {
                            "attributeStrings.facetValue": [
                              "Adidas"
                            ]
                          }
                        }
                      ]
                    }
                  },
                  "path": "attributeStrings"
                }
              }
            ]
          }
        },
        "aggs": {
          "agg_attr_strings": {
            "nested": {
              "path": "attributeStrings"
            },
            "aggs": {
              "attr_name": {
                "terms": {
                  "field": "attributeStrings.facetName",
                },
                "aggs": {
                  "attr_value": {
                    "terms": {
                      "field": "attributeStrings.facetValue",
                      "size": 1000,
                      "order": [
                        {
                          "_term": "asc"
                        }
                      ]
     } } } } } } } }
  </code></pre>
  
  <p>The only way I can see forward with this model, is to calculate the aggregation for each selected facet and somehow merge the result. But it seems very complex and kind of defeats the point of having the model as described in the article, so I hope there's a more clean solution and someone can give a hint at something to try.</p>