How to aggregate over dynamic fields in elasticsearch?

后端 未结 2 984
不知归路
不知归路 2020-12-29 13:18

I am trying to aggregate over dynamic fields (different for different documents) via elasticsearch. Documents are like following:

[{
   \"name\": \"galaxy no         


        
相关标签:
2条回答
  • 2020-12-29 14:00

    You have to define attributes as nested in your mapping and change the layout of the single attribute values to the fixed layout { key: DynamicKey, value: DynamicValue }

    PUT /catalog
    {
      "settings" : {
        "number_of_shards" : 1
      },
      "mappings" : {
        "article": {
          "properties": {
            "name": { 
              "type" : "string", 
              "index" : "not_analyzed" 
            },
            "price": { 
              "type" : "integer" 
            },
            "attributes": {
              "type": "nested",
              "properties": {
                "key": {
                  "type": "string"
                },
                "value": {
                  "type": "string"
                }
              }
            }
          }  
        }
      }
    }
    

    You may than index your articles like this

    POST /catalog/article
    {
      "name": "shirt",
      "price": 123,
      "attributes": [
        { "key": "type", "value": "clothing"},
        { "key": "size", "value": "m"}
      ]
    }
    
    POST /catalog/article
    {
      "name": "galaxy note",
      "price": 123,
      "attributes": [
        { "key": "type", "value": "phone"},
        { "key": "weight", "value": "140gm"}
      ]
    }
    

    After all you are then able to aggregate over the nested attributes

    GET /catalog/_search
    {
      "query":{
        "match_all":{}
      },     
      "aggs": {
        "attributes": {
          "nested": {
            "path": "attributes"
          },
          "aggs": {
            "key": {
              "terms": {
                "field": "attributes.key"
              },
              "aggs": {
                "value": {
                  "terms": {
                    "field": "attributes.value"
                  }
                }
              }
            }
          }
        }
      }
    }
    

    Which then gives you the information you requested in a slightly different form

    [...]
    "buckets": [
      {
        "key": "type",
        "doc_count": 2,
        "value": {
          "doc_count_error_upper_bound": 0,
          "sum_other_doc_count": 0,
          "buckets": [
          {
            "key": "clothing",
            "doc_count": 1
          }, {
            "key": "phone",
            "doc_count": 1
          }
          ]
        }
      },
    [...]
    
    0 讨论(0)
  • 2020-12-29 14:01

    Not sure if this is what you mean, but this is fairly simple with basic aggregation functionality. Beware I did not include a mapping so with type of multiple words you are getting double results.

    POST /product/atype
    {
       "name": "galaxy note",
       "price": 123,
       "attributes": {
          "type": "phone",
          "weight": "140gm"
       }
    }
    
    POST /product/atype
    {
       "name": "shirt",
       "price": 123,
       "attributes": {
          "type": "clothing",
          "size": "m"
       }
    }
    
    GET /product/_search?search_type=count
    {
      "aggs": {
        "byType": {
          "terms": {
            "field": "attributes.type",
            "size": 10
          }
        }
      }
    }
    
    0 讨论(0)
提交回复
热议问题