如何使用FOQElasticaBundle为Symfony2嵌套查询

时间:2013-02-28 08:37:16

标签: symfony elasticsearch

我在使用FOQElasticaBundle

构建查询时遇到问题

我有3个实体

  • 用户
  • 饭店
  • 气氛

用户可以拥有1个或更多酒店,每个酒店只有1个氛围。 在我的配置文件中,我有:

foq_elastica:
clients:
    default: { host: %elasticsearch.host%, port: %elasticsearch.port% }
indexes:
    MyBundle:
        client: default
        finder:
        types:
            user:
                mappings:
                    id:
                        boost: 10
                        analyzer: fr_case_analyzer
                    name:
                        boost: 5
                        analyzer: fr_case_analyzer
                    hotels:
                        type: "nested"
                        properties:
                            name:
                                boost: 10
                                analyzer: fr_case_analyzer
                            ambiance:
                                boost: 1

我希望能够通过输入他的姓名或酒店名称来搜索用户,并可能在Ambiance类型上添加过滤器。 所以查询看起来应该是这样的:

$mainQuery = new \Elastica_Query_Bool();
$nameQuery = new \Elastica_Query_Bool();
$filtersQuery = new \Elastica_Query_Bool();


//searching in Users' names
$nameQuery = new \Elastica_Query_Text();
$nameQuery->setFieldQuery('name', $searchName);
$nameQuery->setFieldParam('name', 'boost', 5);
$nameQuery->setFieldParam('name', 'type', 'phrase_prefix');

//searching in Hotels' names
$hotelNameQuery = new \Elastica_Query_Text();
$hotelNameQuery->setFieldQuery('name', $searchName);
$hotelNameQuery->setFieldParam('name', 'boost', 3);
$hotelNameQuery->setFieldParam('name', 'type', 'phrase_prefix');

$nestedHotelNameQuery = new \Elastica_Query_Nested();
$nestedHotelNameQuery->setPath('hotels');
$nestedHotelNameQuery->setQuery($hotelNameQuery);

$nameQuery->addShould($nameQuery);
$nameQuery->addShould($nestedHotelNameQuery);

//if filter on ambiance
$ambianceQuery = new \Elastica_Query_Term();
$ambianceQuery->setTerm('ambiance', $arrFilters['ambiance']);

$nestedAmbianceQuery = new \Elastica_Query_Nested();
$nestedAmbianceQuery->setPath('hotels');
$nestedAmbianceQuery->setQuery($ambianceQuery);

$filtersQuery->addMust($nestedAmbianceQuery);

//adding the parameters to the main query
$mainQuery->addMust($nameQuery);
$mainQuery->addMust($filtersQuery);

不幸的是,如果Ambiance过滤器被激活,这不起作用并且不返回任何结果,但如果我只搜索名称,则效果很好。

我做错了什么?

3 个答案:

答案 0 :(得分:0)

我发现为什么它不起作用。 该包实际上在对象上使用__toString()。 因此,我没有查询环境的“id”,而是修改了我的html输入,因此值是环境的名称。

答案 1 :(得分:0)

这是我自己的解决方案版本:

根据elasticsearch文档,我们应该实现一个对json声明的结构:

{
  "query": {
    "bool": {
      "must": [
        { "match": { "title": "eggs" }}, 
        {
          "nested": {
            "path": "comments", 
            "query": {
              "bool": {
                "must": [ 
                  { "match": { "comments.name": "john" }},
                  { "match": { "comments.age":  28     }}
                ]
        }}}}
      ]
}}}

所以要使用symfony 2执行此操作,根据FOSElasticaBundle包,我们将生成以下代码行:

//if filter on ambiance
$ambianceQuery = new \Elastica_Query_Term();
$ambianceQuery->setTerm('ambiance', $arrFilters['ambiance']);
// We will add the the term to the query bool 
$filtersQuery->addMust($ambianceQuery)

$nestedAmbianceQuery = new \Elastica_Query_Nested();
$nestedAmbianceQuery->setPath('hotels');
// we will set the result as argument in the setQuery method.
$nestedAmbianceQuery->setQuery($filtersQuery);


// And finally we add the nested query to the main query bool through addMust. 
$mainQuery->addMust($nestedAmbianceQuery);

希望能帮助他人。

A +

答案 2 :(得分:-1)

刚遇到同样的问题。这对我有用:

..
$ambianceQuery->setTerm('hotels.ambiance', $arrFilters['ambiance']);
..

在Symfony2的FOQElasticaBundle(现在是FOSElasticaBundle)中没有找到任何关于此的示例,但它应该像这样的弹性搜索查询结束:

http://www.elasticsearch.org/guide/reference/query-dsl/nested-query/

可以这样做/测试原始弹性搜索查询:

$queryString = '{..JSON..}';
$boolQuery = new \Elastica_Query_Builder($queryString);