# Faceted search with aggregations

**URL:** <https://discuss.elastic.co/t/faceted-search-with-aggregations/205135>\
**Category:** Elasticsearch\
**Created:** [October 24, 2019, 6:49pm UTC](https://discuss.elastic.co/t/faceted-search-with-aggregations/205135 "2019-10-24T18:49:43Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![decodeit](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/decodeit/32/46023_2.png) [@decodeit](https://discuss.elastic.co/u/decodeit)\
**Post date:** [October 24, 2019, 6:49pm UTC](https://discuss.elastic.co/t/faceted-search-with-aggregations/205135/1 "2019-10-24T18:49:43Z")

</div>

I am trying to do faceted search with aggregation (which I think is the way to do, suggestions are welcome).

so the query below is sending the search term with the aggs.  
`POST events/event/_search { "query": { "multi_match": { "query": "phone", "fields": ["title", "description"], } }, "aggs": { "Brand Filter": { "terms": { "field": "brand.keyword", "size": 80 } }, "size Filter": { "terms": { "field": "size.keyword", "size": 80 } } } }`

however, as an example of what i have similar as facet search

![Capture](https://us1.discourse-cdn.com/elastic/original/3X/b/2/b28d149ef258afda2de1596b2c89e41048fda566.png)

so **if the user selects lets say Samsung and Apple. Where does these appear in query.**

Thanks.

---

<div class="post-metadata">

**Author:** ![simplesmente](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/simplesmente/32/24658_2.png) [@simplesmente](https://discuss.elastic.co/u/simplesmente)\
**Post date:** [October 24, 2019, 9:03pm UTC](https://discuss.elastic.co/t/faceted-search-with-aggregations/205135/2 "2019-10-24T21:03:22Z")

</div>

You need to use the selected content in a bool query using term filter.

If you do want to keep all the options even when the results are filtered after queried, [see this](https://www.elastic.co/guide/en/elasticsearch/reference/7.4/search-request-body.html#request-body-search-post-filter)

There's an example of how to make a filter in the link above as well.

---

<div class="post-metadata">

**Author:** ![decodeit](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/decodeit/32/46023_2.png) [@decodeit](https://discuss.elastic.co/u/decodeit)\
**Post date:** [October 25, 2019, 12:11pm UTC](https://discuss.elastic.co/t/faceted-search-with-aggregations/205135/3 "2019-10-25T12:11:58Z")

</div>

so this is my current query I tried with filter. I am getting error saying

```
`"reason": "[multi_match] malformed query, expected [END_OBJECT] but found [FIELD_NAME]",`

```

`{ "query":{ "multi_match": { "query": "phone", "fields": ["title","description"] }, "bool":{ "filter":[{"term":{"brand":"samsung"}}] } } }`

In addition to this, I would like to know how can I pass an array as "brand": ["samsung","Apple"]

Thanks,

---

<div class="post-metadata">

**Author:** ![simplesmente](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/simplesmente/32/24658_2.png) [@simplesmente](https://discuss.elastic.co/u/simplesmente)\
**Post date:** [October 25, 2019, 8:20pm UTC](https://discuss.elastic.co/t/faceted-search-with-aggregations/205135/4 "2019-10-25T20:20:18Z")

</div>

There you go:

```auto
{
  "query": {
    "bool": {
      "must": [
        {
          "multi_match": {
            "query": "phone",
            "fields": [
              "title",
              "description"
            ]
          }
        }
      ],
      "filter": [
        {
          "terms": {
            "brand": [
              "samsung", "Apple"
            ]
          }
        }
      ]
    }
  }
}

```

---

<div class="post-metadata">

**Author:** ![decodeit](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/decodeit/32/46023_2.png) [@decodeit](https://discuss.elastic.co/u/decodeit)\
**Post date:** [October 28, 2019, 11:54am UTC](https://discuss.elastic.co/t/faceted-search-with-aggregations/205135/5 "2019-10-28T11:54:55Z")

</div>

if my filter is just one word like samsung or Apple. it works fine but if its a phrase like general social survey. even though I have that exact phrase in my index, it gives me zero result. cant the filter be a phrase.

---

<div class="post-metadata">

**Author:** ![simplesmente](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/simplesmente/32/24658_2.png) [@simplesmente](https://discuss.elastic.co/u/simplesmente)\
**Post date:** [October 28, 2019, 3:43pm UTC](https://discuss.elastic.co/t/faceted-search-with-aggregations/205135/6 "2019-10-28T15:43:31Z")

</div>

Yes, it can be a phrase. If you could share the piece of code you're writing and a data sample, it would be easier to help you.

---

<div class="post-metadata">

**Author:** ![decodeit](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/decodeit/32/46023_2.png) [@decodeit](https://discuss.elastic.co/u/decodeit)\
**Post date:** [October 28, 2019, 4:01pm UTC](https://discuss.elastic.co/t/faceted-search-with-aggregations/205135/7 "2019-10-28T16:01:09Z")

</div>

```
`{

```

"query": {  
"bool": {  
"must":  
{  
"multi\_match": {  
"query": " social survey",  
"fields": [  
"title", "abstract"  
]  
}  
},  
"filter":[  
{"match\_phrase": {"survey":{"query": "Aboriginal Peoples survey"}}},  
{"match\_phrase": {"subjects":{"query": "population characteristics"}}}  
]  
}  
}  
}`

i ended up using match\_phrase because the filter query that is selected is a phrase instead of one term. so using terms even though I was able to pass multiple values i was only able to pass a term not a phrase. but now here, each query of the match\_phrase is a faceted search.

Basically, i have a list of survey and list of search, user can select multiple surveys and subjects, how do I handle that.

Thanks for your patience.

---

<div class="post-metadata">

**Author:** ![simplesmente](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/simplesmente/32/24658_2.png) [@simplesmente](https://discuss.elastic.co/u/simplesmente)\
**Post date:** [October 29, 2019, 3:13am UTC](https://discuss.elastic.co/t/faceted-search-with-aggregations/205135/8 "2019-10-29T03:13:01Z")

</div>

What you are doing in there is that it's looking for a "Aboriginal Peoples survey" survey **AND**"population characteristics" subject. Maybe it is the reason why you're not getting anything when fetching it.  
Maybe you need to rearrange the query structure to look for one thing or another.  
You can wrap this filter in a should clause in a bool query and set the minimum\_should\_match option to 1.

---

<div class="post-metadata">

**Author:** ![decodeit](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/decodeit/32/46023_2.png) [@decodeit](https://discuss.elastic.co/u/decodeit)\
**Post date:** [October 29, 2019, 11:41am UTC](https://discuss.elastic.co/t/faceted-search-with-aggregations/205135/9 "2019-10-29T11:41:54Z")

</div>

What you are suggesting is, it will give results if the document matches either survey or the subjects.  
I would like those documents to match who has this survey and this subject both, but here I can only pass a single phrase of subject and survey, I would like to be able to pass an array. I will be storing it as an search template so later on I can just give it a list of subjects and list of surveys.  
any suggestions would be helpful. thanks for your time.

---

<div class="post-metadata">

**Author:** ![simplesmente](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/simplesmente/32/24658_2.png) [@simplesmente](https://discuss.elastic.co/u/simplesmente)\
**Post date:** [November 4, 2019, 1:06pm UTC](https://discuss.elastic.co/t/faceted-search-with-aggregations/205135/10 "2019-11-04T13:06:16Z")

</div>

Sorry about the delay on getting back to you on this.

So, you can git the `terms` a try, like I suggest in here:

```auto
"filter": [
  {
    "terms": {
      "brand": [
        "phrase 1", "phrase 2"
      ]
    }
  }
]

```

If you want to combine more filters, you just need to add them to the filter array and you will get the "AND" result as you wish, like this:

```auto
"filter": [
  {
    "terms": {
      "survey": [
        "phrase 1", "phrase 2"
      ]
    }
  },
  {
    "terms": {
      "subjects": [
        "phrase 1", "phrase 2"
      ]
    }
  }
]

```

Not sure if this is what you're aiming but let me know in any case.

---

<div class="post-metadata">

**Author:** ![decodeit](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/decodeit/32/46023_2.png) [@decodeit](https://discuss.elastic.co/u/decodeit)\
**Post date:** [November 4, 2019, 1:27pm UTC](https://discuss.elastic.co/t/faceted-search-with-aggregations/205135/11 "2019-11-04T13:27:19Z")

</div>

I have tried this. The issue with this is since its terms, its searches for "phrase" and "1" in subjects however, I want it to match the subjects that has exactly" phrase 1". but match\_phrase is not able to take an array. I am actually converting these query in a search template. so the subjects filter should be able to take a list .

---

<div class="post-metadata">

**Author:** ![simplesmente](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/simplesmente/32/24658_2.png) [@simplesmente](https://discuss.elastic.co/u/simplesmente)\
**Post date:** [November 12, 2019, 12:20pm UTC](https://discuss.elastic.co/t/faceted-search-with-aggregations/205135/12 "2019-11-12T12:20:47Z")

</div>

You can use `{{#toJson}}subjects{{/toJson}}`  
See [here](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-template.html#_validating_templates) how to use it.

Hope you find it useful.

---

<div class="post-metadata">

**Author:** ![decodeit](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/decodeit/32/46023_2.png) [@decodeit](https://discuss.elastic.co/u/decodeit)\
**Post date:** [November 12, 2019, 1:59pm UTC](https://discuss.elastic.co/t/faceted-search-with-aggregations/205135/13 "2019-11-12T13:59:43Z")

</div>

where do I put the field I want it to search then. I am trying to figure out the difference between what you gave and this {{#join}}emails{{/join}}

---

<div class="post-metadata">

**Author:** ![simplesmente](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/simplesmente/32/24658_2.png) [@simplesmente](https://discuss.elastic.co/u/simplesmente)\
**Post date:** [November 12, 2019, 5:14pm UTC](https://discuss.elastic.co/t/faceted-search-with-aggregations/205135/14 "2019-11-12T17:14:04Z")

</div>

There's an example in the documentation.

The difference is that `join` will send the values passed through param as a string separated by commas and `json` will send the values as an array.

---

<div class="post-metadata">

**Author:** ![decodeit](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/decodeit/32/46023_2.png) [@decodeit](https://discuss.elastic.co/u/decodeit)\
**Post date:** [November 12, 2019, 6:47pm UTC](https://discuss.elastic.co/t/faceted-search-with-aggregations/205135/15 "2019-11-12T18:47:47Z")

</div>

so now I am using it like this:

```
   `{

```

"source": {  
"query": {  
"bool":{  
"must":[  
{"match\_phrase": {"subjects.en": "{{#join}}subjects{{/join}}"}},  
{"match\_phrase": {"survey.title.en": "{{#join}}surveys{{/join}}"}}  
]  
}  
}  
},  
"params": {  
"subjects": ["Social Well-being", "Social Networks"],  
"surveys": ["General Social Survey"]  
}  
}`

but its giving empty result. I want to use match phrase because it needs to match the phrase provided exactly.

---

<div class="post-metadata">

**Author:** ![simplesmente](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/simplesmente/32/24658_2.png) [@simplesmente](https://discuss.elastic.co/u/simplesmente)\
**Post date:** [November 13, 2019, 1:02pm UTC](https://discuss.elastic.co/t/faceted-search-with-aggregations/205135/16 "2019-11-13T13:02:59Z")

</div>

Instead of passing only the terms as a parameter, you might need to pass the whole match phrase condition.

I think you could do something like this:

```auto
"source": {
  "query": {
    "bool":{
      "must":[
        {{#join}}subjects{{/join}}
        {{#join}}surveys{{/join}}
      ]
    }
  }
},
"params": {
  "subjects": [
    {"match_phrase": {"subjects.en": "Social Well-being"}},
    {"match_phrase": {"subjects.en": "Social Networks"}},
  ],
  "surveys": [
    {"match_phrase": {"subjects.en": "General Social Survey"}}
  ]
}

```

---

<div class="post-metadata">

**Author:** ![decodeit](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/decodeit/32/46023_2.png) [@decodeit](https://discuss.elastic.co/u/decodeit)\
**Post date:** [November 14, 2019, 1:57pm UTC](https://discuss.elastic.co/t/faceted-search-with-aggregations/205135/17 "2019-11-14T13:57:18Z")

</div>

This is giving error,

```
`error": {
"root_cause": [
  {
    "type": "parsing_exception",
    "reason": "Could not parse inline template",
    "line": 6,
    "col": 9
  }
],
"type": "x_content_parse_exception",
"reason": "[6:9] [search_template] failed to parse field [source]",
"caused_by": {
  "type": "parsing_exception",
  "reason": "Could not parse inline template",
  "line": 6,
  "col": 9,
  "caused_by": {
    "type": "json_parse_exception",
    "reason": "Unexpected character ('{' (code 123)): was expecting double-quote to start field name\n at [Source: org.elasticsearch.transport.netty4.ByteBufStreamInput@3c783eba; line: 6, column: 11]",
    "suppressed": [
      {
        "type": "illegal_state_exception",
        "reason": "Failed to close the XContentBuilder",
        "caused_by": {
          "type": "i_o_exception",
          "reason": "Unclosed object or array found"`
```

---

<div class="post-metadata">

**Author:** ![simplesmente](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/simplesmente/32/24658_2.png) [@simplesmente](https://discuss.elastic.co/u/simplesmente)\
**Post date:** [November 14, 2019, 5:31pm UTC](https://discuss.elastic.co/t/faceted-search-with-aggregations/205135/18 "2019-11-14T17:31:21Z")

</div>

Try this:

```auto

  "source": "{\"query\": {\"bool\":{\"must\":[{{#toJson}}subjects{{/toJson}},{{#toJson}}surveys{{/toJson}}]}}}",
  "params": {
    "subjects": [
      {"match_phrase": {"subjects.en": "Social Well-being"}},
      {"match_phrase": {"subjects.en": "Social Networks"}}
    ],
    "surveys": [
      {"match_phrase": {"survey.title.en": "General Social Survey"}}
    ]
  }

```

I tested this in my own index and it should work fine.

---

<div class="post-metadata">

**Author:** ![decodeit](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/decodeit/32/46023_2.png) [@decodeit](https://discuss.elastic.co/u/decodeit)\
**Post date:** [November 14, 2019, 6:21pm UTC](https://discuss.elastic.co/t/faceted-search-with-aggregations/205135/19 "2019-11-14T18:21:55Z")

</div>

would there be "and" or "OR" relation between subjects and surveys?  
and what about between subjects itself. will there be an "OR"

---

<div class="post-metadata">

**Author:** ![simplesmente](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/simplesmente/32/24658_2.png) [@simplesmente](https://discuss.elastic.co/u/simplesmente)\
**Post date:** [November 14, 2019, 6:37pm UTC](https://discuss.elastic.co/t/faceted-search-with-aggregations/205135/20 "2019-11-14T18:37:34Z")

</div>

All "and". This is what you wanted in the first place, isn't it?

[Next page](https://discuss.elastic.co/t/faceted-search-with-aggregations/205135.md?page=2)
