多字值问题汇总

时间:2018-12-19 22:23:45

标签: php elasticsearch

我正在基于Elasticsearch构建分层导航。我的产品具有“品牌”字段。例如,我有2个品牌-Tommy Jeans和Tommy Hilfiger。当我尝试使用以下查询汇总结果

$params = [
    'index' => 'my_index',
    'type' => 'my_type',
    'body' => [
        'query' => [
            'term'  => [
                'brand' => 'tommy'
            ]
        ],
        'aggs' => [
            'brand' => [
                'terms' => [
                    'field' => 'brand',
                ]
            ]
        ]
    ]
];

我希望方括号中有2个结果-Tommy Hilfiger和Tommy Jeans都有结果计数,但就我而言,是这样的

[aggregations] => Array
    (
        [brand] => Array
            (
                [doc_count_error_upper_bound] => 0
                [sum_other_doc_count] => 0
                [buckets] => Array
                    (
                        [0] => Array
                            (
                                [key] => tommy
                                [doc_count] => 6
                            )

                        [1] => Array
                            (
                                [key] => hilfiger
                                [doc_count] => 4
                            )

                        [2] => Array
                            (
                                [key] => jeans
                                [doc_count] => 2
                            )

                    )

            )

    )

我该如何解决?

2 个答案:

答案 0 :(得分:1)

这可以通过使brand类型的text字段并向其添加一个子字段keyword和类型keyword来实现。然后,您需要对字段term使用brand查询来过滤结果并在字段brand.keyword上进行汇总

因此映射将为:

{
  "mappings": {
    "_doc": {
      "properties": {
        "brand": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword"
            }
          }
        }
      }
    }
  }
}

更新评论:映射旧版本的es(2.x):

{
  "mappings": {
    "_doc": {
      "properties": {
        "brand": {
          "type": "string",
          "fields": {
            "keyword": {
              "type": "string",
              "index": "not_analyzed"
            }
          }
        }
      }
    }
  }
}

以下是查询:

{
  "query": {
    "bool": {
      "filter": [
        {
          "term": {
            "brand": "tommy"
          }
        }
      ]
    }
  },
  "aggs": {
    "brand": {
      "terms": {
        "field": "brand.keyword"
      }
    }
  }
}

答案 1 :(得分:0)

最后,我发现了我的问题。这是一个可行的示例(基于Nishant Saini的回答)

use Elasticsearch\ClientBuilder;

require 'vendor/autoload.php';

echo '<pre>';

$client = ClientBuilder::create()->build();

$params = [
    'index' => 'my_index',
    'body' => [
        'mappings' => [
            'my_type' => [
                'properties' => [
                    'brand' => [
                        'type'  => 'string',
                        'fields'    => [
                            'keyword'   => [
                                'type'  => 'string',
                                'index' => 'not_analyzed'
                            ]
                        ]
                    ],
                    'color' => [
                        'type'  => 'string',
                        'fields'    => [
                            'keyword'   => [
                                'type'  => 'string',
                                'index' => 'not_analyzed'
                            ]
                        ]
                    ],
                    'category' => [
                        'type'  => 'string',
                        'fields'    => [
                            'keyword'   => [
                                'type'  => 'string',
                                'index' => 'not_analyzed'
                            ]
                        ]
                    ],
                    'id' => [
                        'type'  => 'integer',
                    ]   
                ]
            ]
        ]
    ]
];

$client->indices()->create($params);

$items = [
    [
        'id'        => 1,
        'category'  => 'Jackets',
        'brand'     => 'Tommy Hilfiger',
        'color'     => 'Red'
    ],
    [
        'id'        => 2,
        'category'  => 'Jeans',
        'brand'     => 'Tommy Jeans',
        'color'     => 'Navy'
    ],
    [
        'id'        => 3,
        'category'  => 'Shirts',
        'brand'     => 'Tommy Hilfiger',
        'color'     => 'Maroon'
    ],
    [
        'id'        => 4,
        'category'  => 'Trousers',
        'brand'     => 'Tommy Jeans',
        'color'     => 'Grey'
    ],
    [
        'id'        => 5,
        'category'  => 'Shirts',
        'brand'     => 'Tommy Hilfiger',
        'color'     => 'Grey'
    ],
    [
        'id'        => 6,
        'category'  => 'Sneakers',
        'brand'     => 'Tommy Jeans',
        'color'     => 'Grey'
    ],
    [
        'id'        => 7,
        'category'  => 'Sneakers',
        'brand'     => 'Tommy Jeans',
        'color'     => 'Grey'
    ]
];

foreach ($items as $item) {
    $params = [
        'index' => 'my_index',
        'type' => 'my_type',
        'id' => $item['id'],
        'body' => [
            'brand'             => $item['brand'],
            'color'             => $item['color'],
            'category'          => $item['category'],
        ]
    ];

    $client->index($params);
}

$params = [
    'index' => 'my_index',
    'body' => [
        'query' => [
            'bool' => [
                'must' => [
                    [ 'match' => [ 'brand' => 'tommy' ] ],
                    [ 'match' => [ 'color' => 'grey' ] ]
                ]
            ]
        ],
        'aggs' => [
            'brands' => [
                'terms' => [
                    'field' => 'brand.keyword',
                ],
            ],
            'colors' => [
                'terms' => [
                    'field' => 'color.keyword',
                ]
            ],
            'categories' => [
                'terms' => [
                    'field' => 'category.keyword',
                ]
            ]
        ]
    ]
];

$response = $client->search($params);
print_r($response);

结果是

Array
(
    [brands] => Array
        (
            [doc_count_error_upper_bound] => 0
            [sum_other_doc_count] => 0
            [buckets] => Array
                (
                    [0] => Array
                        (
                            [key] => Tommy Jeans
                            [doc_count] => 3
                        )

                    [1] => Array
                        (
                            [key] => Tommy Hilfiger
                            [doc_count] => 1
                        )

                )

        )

    [categories] => Array
        (
            [doc_count_error_upper_bound] => 0
            [sum_other_doc_count] => 0
            [buckets] => Array
                (
                    [0] => Array
                        (
                            [key] => Sneakers
                            [doc_count] => 2
                        )

                    [1] => Array
                        (
                            [key] => Shirts
                            [doc_count] => 1
                        )

                    [2] => Array
                        (
                            [key] => Trousers
                            [doc_count] => 1
                        )

                )

        )

    [colors] => Array
        (
            [doc_count_error_upper_bound] => 0
            [sum_other_doc_count] => 0
            [buckets] => Array
                (
                    [0] => Array
                        (
                            [key] => Grey
                            [doc_count] => 4
                        )

                )

        )

)