Elasticsearch - 不同的价值观,而不是计数

时间:2017-05-17 20:57:16

标签: php elasticsearch foselasticabundle

我正在尝试做类似于这个SQL查询的事情:

SELECT * FROM table WHERE fileContent LIKE '%keyword%' AND company_id = '1' GROUP BY email

阅读帖子similar to this后,我有了这个:

{
    "query": {
        "bool": {
            "must": [{
                "match": {
                    "fileContent": {
                        "query": "keyword"
                    }
                }
            }],
            "filter": [{
                "terms": {
                    "company_id": [1]
                }
            }]
        }
    },
    "aggs": {
        "group_by_email": {
            "terms": {
                "field": "email",
                "size": 1000
            }
        }
    },
    "size": 0
}

字段映射是:

{
  "cvs" : {
    "mappings" : {
      "application" : {
        "_meta" : {
          "model" : "Acme\\AppBundle\\Entity\\Application"
        },
        "dynamic_date_formats" : [ ],
        "properties" : {
          "email" : {
            "type" : "keyword"
          },
          "fileContent" : {
            "type" : "text"
          },
          "company_id" : {
            "type" : "text"
          }
        }
      }
    }
  }
}

...由Symfony config.yml生成:

fos_elastica:
    clients:
        default:
            host: "%elastica.host%"
            port: "%elastica.port%"
    indexes:
        cvs:
            client: default
            types:
               application:
                    properties:
                        fileContent: ~
                        email:
                          index: not_analyzed
                        company_id: ~
                    persistence:
                        driver: orm
                        model: Acme\AppBundle\Entity\Application
                        provider: ~
                        finder: ~

过滤器工作正常,但我发现hits:hits没有返回任何项目(或者如果我删除了size:0,则所有结果都与搜索匹配),而aggregations:group_by_email:buckets包含了计数但是不是记录本身。分组的记录不会被返回,这就是我需要的记录。

我还尝试使用查询构建器使用FOSElasticBundle,如果这是您的首选风格(这可行,但没有分组/聚合):

$boolQuery = new \Elastica\Query\BoolQuery();

$filterKeywords = new \Elastica\Query\Match();
$filterKeywords->setFieldQuery('fileContent', 'keyword');
$boolQuery->addMust($filterKeywords);

$filterUser = new \Elastica\Query\Terms();
$filterUser->setTerms('company_id', array('1'));
$boolQuery->addFilter($filterUser);

$finder = $this->get('fos_elastica.finder.cvs.application');

感谢。

3 个答案:

答案 0 :(得分:1)

为此,您需要terms在您已使用的 "aggs": { "group_by_email": { "terms": { "field": "email", "size": 1000 }, "aggs": { "sample_docs": { "top_hits": { "size": 100 } } } } } 内:

ps

答案 1 :(得分:0)

在安德烈的回答中,我似乎是{p> top_hits:{size:1}。这将为聚合中的每个桶返回一条记录

  "aggs": {
    "group_by_email": {
      "terms": {
        "field": "email",
        "size": 1000
      },
      "aggs": {
        "sample_docs": {
          "top_hits": {
            "size": 1
          }
        }
      }
    }
  }

参考:top_hits

答案 2 :(得分:0)

top_hits也帮助了我。我也遇到了一些麻烦,但最终想出了解决方法。 这是我的解决方案:

{
    "query": {
        "nested": {
            "path": "placedOrders",
            "query": {
                "bool": {
                    "must": [
                        {
                            "term": {
                                "placedOrders.ownerId": "0a9fdef0-4508-4f9c-aa8c-b3984e39ad1e"
                            }
                        }
                    ]
                }
            }
        }
    },
    "aggs": {
        "custom_name1": {
            "nested": {
                "path": "placedOrders"
            },
            "aggs": {
                "custom_name2": {
                    "terms": {
                        "field": "placedOrders.propertyId"
                    },
                    "aggs": {
                        "custom_name3": {
                            "top_hits": {
                                "size": 1,
                                "sort": [
                                    {
                                        "placedOrders.propertyId": {
                                            "order": "desc"
                                        }
                                    }
                                ]
                            }
                        }
                    }
                }
            }
        }
    }
}