Facets resulting in objects instead of primitive types


(Stefan) #1

Hi fellows

I checked this forum and stackoverflow but couldn't find a matching discussion while thinking this must arise to someone before already. So I'd be happy for any help. Let's come to the point:

I want to perform a search with facet calculation returning objects as facets insteads of single values.

My mapping looks as follows (excerpt):

"myConfiguration": {"properties": {"paint": {"properties": {"code": {"type": "string"},"text": {"type": "string"}}}}}

My query currently looks like this:

{
  "facets": {
    "tag": {
      "terms": { "field": "myConfiguration.paint.code" }
}  }  }

This works for the case of retrieving all paint codes used in my data set.

{
  "facets": {
    "tag": {
      "_type": "terms", "missing": 1, "total": 525, "other": 0,
      "terms": [
        {
          "term": "4",
          "count": 20
        },
        {
          "term": "2",
          "count": 10
        },
        {
          "term": "5",
          "count": 3
        }
      ]    }  } }

However, the text is what I am also interested in. What I rather want to have is something like the following:

{
  "facets": {
    "tag": {
      "_type": "terms", "missing": 1, "total": 525, "other": 0,
      "terms": [
        {
          "term": {"code":"4", "text":"yellow"},
          "count": 20
        },
        {
          "term": {"code":"2", "text":"black"},
          "count": 10
        },
        {
          "term": {"code":"5", "text":"white"},
          "count": 3
        }
      ]     }   } }

Is this possible at all and if yes how can I achieve that? Thanks in advance!!!
Stefan

(keyword: facets, aggregation, term, query, search)


Aggregations over similarly-structured objects but in different paths
(Camilo Sierra) #2

Hi Stefan, i dont know the version of your elasticsearch but dont use anymore the facets (they are deprecated) use the aggregations.

and for your example you can use the sub_aggregations, your query will be more complex and the answer also, but you can get all the information in one query.

i let you check http://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-nested-aggregation.html for the nested,

and http://www.elastic.co/guide/en/elasticsearch/reference/1.x/search-aggregations.html this for get some examples of sub_aggregations


(Camilo Sierra) #3

if you read this link and you dont arrive to made your query, you can send some examples with the *put request for your mapping and data, and i can try to help you to made this query.

Example how send the examples with your mapping and data :

PUT index/type
{
    "type" : {
        "properties" : {
            "foo" : {"type" : "string", "store" : true }
        }
    }
}
PUT index/type/1
    {
      "foo": "bar"
    }
    GET index/type/_search
    {
      "query": {
        "match": {
          "foo": "bar"
        }
      }
    }

(Stefan) #4

Hi Camilo_Sierra,

thanks for you immediate response! I will definitely take a look at your suggestions.

Unfortunately at the moment I stuck with "facets" since my 'problem query' is so-to-say an extension of an existing query with facets. Recreating everything in terms of aggregation is quite an effort.

Anyhow, thanks a lot for your response and offer. If I have further questions I am happy that I can ask you again.

Cheers, Stefan


(Camilo Sierra) #5

i never made one request like that with facets, sorry @sjtuner ! anyway tried to migrate, the aggregations are really amazing, faster...etc

good luck


(Matt Weber) #6

You really should use aggregations as @Camilo_Sierra recommended. It is very little effort to convert from facets to aggregations and will be well worth the investment. If you can't do that your only option would be using script fields [1] to join the values together then use that field [2] during faceting so you would get values like:

"yellow_4", count = 20
"black_2", count = 10
"white_5", count = 3

Then at runtime you can re-split the values back up if needed.

[1] https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-script-fields.html
[2] http://www.elastic.co/guide/en/elasticsearch/reference/current/search-facets-terms-facet.html#_script_field


(Stefan) #7

The script fields are actually something I have seen too and the approach you mentioned, mattweber, came up to mind mind as well. In the end I just failed to make that work. Maybe you can give me some practical hints?

Anyhow, I will definetly also investigate into migrating to aggregations.

Thanks again for you help. You have an awesome response time.

Stefan


(Matt Weber) #8

This should work @sjtuner

{"query":{"match_all": {}}, 
 "facets":{
     "paints": {
         "terms": {
             "script":"_source.paint.text + \"_\" + _source.paint.code"}}}}

Make sure you have scripting enabled.


(Stefan) #9

That actually worked for me, thanks a lot. Anyway, I will also check out aggregations. :smile:

Best regards, Stefan


(Stefan) #10

Hi @Camilo_Sierra,

in the meantime I migrated to aggregations. It surprisingly easy and even more diffcult-appearing aggs were implemented pretty fast :slight_smile:

Thanks again for your help.

Stefan

PS: I have another question towards aggregations but I will ask this in a different thread :wink:


(Stefan) #11

Hi @Camilo_Sierra and friends :smile:

unfortunately it turned out that my first solution did actually not exactly what I had in mind. Now i'd kindly take your offer for more help. Lets consider the following example (requests are minified to keep this post's size limited)

PUT index/a/_mapping
{"a":{"properties":{"b":{"properties":{"c":{"properties":{"code":{"type":"string"},"text":{"type":"string"}}}}}}}}

PUT index/a/1
{"a":{"b":{"c":[{"code":"123","text":"abc"},{"code":"456","text":"def"}]}}}

PUT index/a/2
{"a":{"b":{"c":[{"code":"123","text":"abc"},{"code":"789","text":"ghi"}]}}}

What I want to have is all available c-elements, i.e., code as well as related text. My aggregation looks as follows:

POST index/a/_search
{"size":0,"aggs":{"allCCodes":{"terms":{"field":"a.b.c.code"},"aggs":{"allCTexts":{"terms":{"field":"a.b.c.text"}}}}}}

Unfortunately it returned the following:
123 ---> abc, def, ghi
456 ---> abc, def
789 ---> abc, ghi

What I want
123 ---> abc
456 ---> def
789 ---> ghi

Any ideas?

Best regards and wishes,
Stefan


(Stefan) #12

Well, since this is at least partially new stuff, a new thread makes more sense here. I close this ticket therefore and create a new one. Thanks for your help again!!


(system) #13