# How can I facet based on fields with hits?

**URL:** <https://discuss.elastic.co/t/how-can-i-facet-based-on-fields-with-hits/4334>\
**Category:** Elasticsearch\
**Created:** [May 3, 2011, 8:00pm UTC](https://discuss.elastic.co/t/how-can-i-facet-based-on-fields-with-hits/4334 "2011-05-03T20:00:18Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Ellery\_Crane\_2](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/ellery_crane_2/32/3369_2.png) [@Ellery\_Crane\_2](https://discuss.elastic.co/u/Ellery_Crane_2)\
**Post date:** [May 3, 2011, 8:00pm UTC](https://discuss.elastic.co/t/how-can-i-facet-based-on-fields-with-hits/4334/1 "2011-05-03T20:00:18Z")

</div>

I'm brand new to ElasticSearch, and exploring the wonderful faceting  
features. I have a business use case I'm trying to construct a query  
for, and I was hoping someone could point me toward a more elegant  
(and performant) solution.

I want to perform a query against some set of fields (usually all of  
them) in my documents, and then set up facets defining results with  
hits in specific fields.

For example, take the following data:

curl -XPUT '[http://localhost:9200/test/contact/1](http://localhost:9200/test/contact/1)' -d '  
{  
"name": {  
"first": "Brad",  
"last": "Smith"  
},  
"address":{  
"street": "123 Smithsonian Avenue",  
"city": "Albany",  
"state": "NY"  
}  
}'

curl -XPUT '[http://localhost:9200/test/contact/2](http://localhost:9200/test/contact/2)' -d '  
{  
"name": {  
"first": "Jane",  
"last": "Doe"  
},  
"address":{  
"street": "1 Green Valley Blvd.",  
"city": "Smithville",  
"state": "NY"  
}  
}'

curl -XPUT '[http://localhost:9200/test/contact/3](http://localhost:9200/test/contact/3)' -d '  
{  
"name": {  
"first": "Janet",  
"last": "Green"  
},  
"address":{  
"street": "456 Goldsmith Place",  
"city": "Bradley",  
"state": "MN"  
}  
}'

I want to query all fields in all documents, and then facet based on  
the field it found the term in. One way I've found to do this is as  
follows:

curl -XPOST [http://localhost:9200/test/contact/\_search?pretty=true](http://localhost:9200/test/contact/_search?pretty=true) -d  
'{  
"query": {  
"query\_string": {  
"query": "_smith_"  
}  
},  
facets: {  
names\_facet: {  
query: {  
query\_string: {  
query: "_smith_",  
fields: ["name.first", "name.last"],  
use\_dis\_max: true  
}  
}  
},  
address\_facet: {  
query: {  
query\_string: {  
query: "_smith_",  
fields: [ "address.street", "address.city",  
"address.state"],  
use\_dis\_max: true  
}  
}  
}  
}  
}'

This gives me the results I'm after; 3 hits total, with the following  
facet counts:

"facets" : {  
"names\_facet" : {  
"\_type" : "query",  
"count" : 1  
},  
"address\_facet" : {  
"\_type" : "query",  
"count" : 3  
}  
}

The problem with this method is that duplicating the query across each  
facet seems both ugly and expensive. Is there some way I can facet  
based solely on fields that have hits? I looked at using the terms  
filter, but I'm not after a list of the common terms in each field. I  
just want to know how many hits in the original query happened in each  
set of fields. Is there something in the Query DSL I can use towards  
this end?

Thanks!

---

<div class="post-metadata">

**Author:** ![kimchy](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/kimchy/32/44952_2.png) [@kimchy](https://discuss.elastic.co/u/kimchy)\
**Post date:** [May 4, 2011, 8:10am UTC](https://discuss.elastic.co/t/how-can-i-facet-based-on-fields-with-hits/4334/2 "2011-05-04T08:10:34Z")

</div>

There isn't an option to facet just on the fields that have hits, since that information is not available during search unless you execute specific query facet on each one, as you do, which is, as you said, not per wise.  
On Tuesday, May 3, 2011 at 11:00 PM, Ellery Crane wrote:

> I'm brand new to Elasticsearch, and exploring the wonderful faceting  
> features. I have a business use case I'm trying to construct a query  
> for, and I was hoping someone could point me toward a more elegant  
> (and performant) solution.
> 
> I want to perform a query against some set of fields (usually all of  
> them) in my documents, and then set up facets defining results with  
> hits in specific fields.
> 
> For example, take the following data:
> 
> curl -XPUT '[http://localhost:9200/test/contact/1](http://localhost:9200/test/contact/1)' -d '  
> {  
> "name": {  
> "first": "Brad",  
> "last": "Smith"  
> },  
> "address":{  
> "street": "123 Smithsonian Avenue",  
> "city": "Albany",  
> "state": "NY"  
> }  
> }'
> 
> curl -XPUT '[http://localhost:9200/test/contact/2](http://localhost:9200/test/contact/2)' -d '  
> {  
> "name": {  
> "first": "Jane",  
> "last": "Doe"  
> },  
> "address":{  
> "street": "1 Green Valley Blvd.",  
> "city": "Smithville",  
> "state": "NY"  
> }  
> }'
> 
> curl -XPUT '[http://localhost:9200/test/contact/3](http://localhost:9200/test/contact/3)' -d '  
> {  
> "name": {  
> "first": "Janet",  
> "last": "Green"  
> },  
> "address":{  
> "street": "456 Goldsmith Place",  
> "city": "Bradley",  
> "state": "MN"  
> }  
> }'
> 
> I want to query all fields in all documents, and then facet based on  
> the field it found the term in. One way I've found to do this is as  
> follows:
> 
> curl -XPOST [http://localhost:9200/test/contact/\_search?pretty=true](http://localhost:9200/test/contact/_search?pretty=true) -d  
> '{  
> "query": {  
> "query\_string": {  
> "query": "_smith_"  
> }  
> },  
> facets: {  
> names\_facet: {  
> query: {  
> query\_string: {  
> query: "_smith_",  
> fields: ["name.first", "name.last"],  
> use\_dis\_max: true  
> }  
> }  
> },  
> address\_facet: {  
> query: {  
> query\_string: {  
> query: "_smith_",  
> fields: [ "address.street", "address.city",  
> "address.state"],  
> use\_dis\_max: true  
> }  
> }  
> }  
> }  
> }'
> 
> This gives me the results I'm after; 3 hits total, with the following  
> facet counts:
> 
> "facets" : {  
> "names\_facet" : {  
> "\_type" : "query",  
> "count" : 1  
> },  
> "address\_facet" : {  
> "\_type" : "query",  
> "count" : 3  
> }  
> }
> 
> The problem with this method is that duplicating the query across each  
> facet seems both ugly and expensive. Is there some way I can facet  
> based solely on fields that have hits? I looked at using the terms  
> filter, but I'm not after a list of the common terms in each field. I  
> just want to know how many hits in the original query happened in each  
> set of fields. Is there something in the Query DSL I can use towards  
> this end?
> 
> Thanks!

---

<div class="post-metadata">

**Author:** ![Ellery\_Crane\_2](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/ellery_crane_2/32/3369_2.png) [@Ellery\_Crane\_2](https://discuss.elastic.co/u/Ellery_Crane_2)\
**Post date:** [May 4, 2011, 2:57pm UTC](https://discuss.elastic.co/t/how-can-i-facet-based-on-fields-with-hits/4334/3 "2011-05-04T14:57:40Z")

</div>

Would there be some way to tap into the logic which is aggregating the  
field highlighting in order to get the kind of facet counting I'm  
after? In other words, facet on whether or not there is a highlight  
found for a given field?

On May 4, 4:10 am, Shay Banon [shay.ba...@elasticsearch.com](mailto:shay.ba...@elasticsearch.com) wrote:

> There isn't an option to facet just on the fields that have hits, since that information is not available during search unless you execute specific query facet on each one, as you do, which is, as you said, not per wise.

---

<div class="post-metadata">

**Author:** ![kimchy](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/kimchy/32/44952_2.png) [@kimchy](https://discuss.elastic.co/u/kimchy)\
**Post date:** [May 4, 2011, 4:41pm UTC](https://discuss.elastic.co/t/how-can-i-facet-based-on-fields-with-hits/4334/4 "2011-05-04T16:41:04Z")

</div>

No, and honestly, not sure how to implement something like that in a performant manner. Requires some thinking.  
On Wednesday, May 4, 2011 at 5:57 PM, Ellery Crane wrote:

> Would there be some way to tap into the logic which is aggregating the  
> field highlighting in order to get the kind of facet counting I'm  
> after? In other words, facet on whether or not there is a highlight  
> found for a given field?
> 
> On May 4, 4:10 am, Shay Banon [shay.ba...@elasticsearch.com](mailto:shay.ba...@elasticsearch.com) wrote:
> 
> > There isn't an option to facet just on the fields that have hits, since that information is not available during search unless you execute specific query facet on each one, as you do, which is, as you said, not per wise.

---

<div class="post-metadata">

**Author:** ![Ellery\_Crane\_2](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/ellery_crane_2/32/3369_2.png) [@Ellery\_Crane\_2](https://discuss.elastic.co/u/Ellery_Crane_2)\
**Post date:** [May 6, 2011, 2:51pm UTC](https://discuss.elastic.co/t/how-can-i-facet-based-on-fields-with-hits/4334/5 "2011-05-06T14:51:47Z")

</div>

On May 4, 12:41 pm, Shay Banon [shay.ba...@elasticsearch.com](mailto:shay.ba...@elasticsearch.com) wrote:

> No, and honestly, not sure how to implement something like that in a performant manner. Requires some thinking.

Thank you for the prompt reply- it is appreciated.

I suppose I can deal with the performance hit to get the behavior I'm  
after- just being able to facet in the fashion I used in my initial  
post is extraordinary! Still, being able achieve this functionality in  
a more elegant and performant manner would be amazing. If a way of  
doing so ever occurs to you, be assured that at least one of your  
users would be most happy for the feature 🙂

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/elastic/original/3X/1/a/1ac57faf039f6b580b3f104ef42a2a89e41014de.png) [@system](https://discuss.elastic.co/u/system)\
**Post date:** [July 6, 2017, 4:06am UTC](https://discuss.elastic.co/t/how-can-i-facet-based-on-fields-with-hits/4334/6 "2017-07-06T04:06:49Z")

</div>


