【问题标题】:Count query with PHP Elastica and Symfony2 FosElasticaBundle使用 PHP Elastica 和 Symfony2 FosElasticaBundle 进行计数查询
【发布时间】:2014-11-26 10:32:07
【问题描述】:

我正在使用 FosElasticaBundle (@dev) 进行 Symfony 2.5.6 项目。

在我的项目中,我只需要获取 Elastic Search 请求的总点击数。也就是说,我使用普通请求查询 Elastic Search,但通过特殊的“计数”URL

localhost:9200/_search?search_type=count

注意“search_type=count”网址参数。

这是示例查询:

{
  "query": {
    "filtered": {
      "query": {
        "match_all": []
      },
      "filter": {
        "bool": {
          "must": [
            {
              "terms": {
                "media.category.id": [
                  681
                ]
              }
            }
          ]
        }
      }
    }
  },
  "sort": {
    "published_at": {
      "order": "desc"
    }
  },
  "size": 1
}

结果包含正常的 JSON 响应,但hits 部分中没有任何文档。从这个回复中我很容易得到总数:

{
    "took": 1,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "failed": 0
    },
    "hits": {
        "total": 81,
        "max_score": 0,
        "hits": [ ]
    }
}

好的,hits.total == 81

现在,我无法通过 FOSElasticaBundle 从存储库中找到任何解决方案。

我试过这个:

$query = (...) // building the Elastica query here
$count = $this->finder->findPaginated(
    $query,
    array(ES::OPTION_SEARCH_TYPE => ES::OPTION_SEARCH_TYPE_COUNT)
)->getNbResults();

但我尝试加载类“Pagerfanta”。我不想要 Pagerfanta。

然后这个:

$count = $this->finder->createPaginatorAdapter(
    $query,
    array(ES::OPTION_SEARCH_TYPE => ES::OPTION_SEARCH_TYPE_COUNT)
)->getTotalHits();

但它总是给我 0。

如果我可以从存储库访问 Elastica Finder 服务会很容易(然后我可以从查询搜索中获得一个 ResultSet,并且这个 ResultSet 有一个正确的 getTotalHits() 方法)。但是来自存储库的服务......你知道的。

感谢您提供任何帮助或线索!

【问题讨论】:

    标签: elasticsearch elastica foselasticabundle


    【解决方案1】:

    我面临着同样的挑战,从 repo 内部访问可搜索界面。这是我最终得到的结果:

    创建AcmeBundle\Elastica\ExtendedTransformedFinder。这只是扩展了TransformedFinder 类并使searchable 接口可访问。

    <?php
    
    namespace AcmeBundle\Elastica;
    
    use FOS\ElasticaBundle\Finder\TransformedFinder;
    
    class ExtendedTransformedFinder extends TransformedFinder
    {
    
        /**
         * @return \Elastica\SearchableInterface
         */
        public function getSearch()
        {
            return $this->searchable;
        }
    
    }
    

    让包使用我们的新类;在service.yml:

    parameters:
          fos_elastica.finder.class: AcmeBundle\Elastica\ExtendedTransformedFinder
    

    然后在 repo 中使用我们类的 getSearch 方法并做你想做的事:)

    class SomeSearchRepository extends Repository
    {
        public function search(/* ... */)
        {
            // create and set your query as you like
            $query = Query::create();
    
            // ...
    
            // then run a count query
            $count = $this->finder->getSearch()->count($query);
    
        }
    }
    

    注意这适用于我的 3.1.x 版本。应该从 3.0.x 开始工作。

    【讨论】:

    • 确认,与当前的 3.1.x-dev 配合得很好。谢谢!
    【解决方案2】:

    好的,所以,我们开始吧:这是不可能

    从版本 3.1.x-dev (2d8903a) 起,您无法从 FOSElasticaBundle 获取弹性搜索返回的匹配文档总数,因为此捆绑包不公开此值。

    RawPaginatorAdapter::getTotalHits() 方法包含以下代码:

    return $this->query->hasParam('size')
        ? min($this->totalHits, (integer) $this->query->getParam('size'))
        : $this->totalHits;
    

    这会阻止在不需要任何文档的情况下获得正确的$this-&gt;totalHits。事实上,如果你将 size 设置为 0,告诉 elasticsearch 不返回任何文档,只返回元信息,RawPaginatorAdapter::getTotalHits() 将返回 0。

    所以 FosElasticaBundle 不提供了解此总点击次数的方法,您只能直接通过 Elastica 库来做到这一点。当然,缺点是 Elastica 查找器在 \FOS\ElasticaBundle\Repository 中原生可用。您必须创建一项新服务,进行一些注入,然后重新启动您的服务,而不是用于存储库的 FOSElasticaBundle 服务...哎呀。

    我选择了另一个路径,我 fork https://github.com/FriendsOfSymfony/FOSElasticaBundle 并更改了方法代码如下:

    /**
     * Returns the number of results.
     *
     * @param boolean $genuineTotal make the function return the `hits.total`
     * value of the search result in all cases, instead of limiting it to the
     * `size` request parameter.
     * @return integer The number of results.
     */
    public function getTotalHits($genuineTotal = false)
    {
        if ( ! isset($this->totalHits)) {
            $this->totalHits = $this->searchable->search($this->query)->getTotalHits();
        }
    
    return $this->query->hasParam('size') && !$genuineTotal
        ? min($this->totalHits, (integer) $this->query->getParam('size'))
        : $this->totalHits;
    }
    

    $genuineTotal boolean 恢复弹性搜索行为,而不会引入任何 BC 中断。我也可以将其命名为 $ignoreSize 并以相反的方式使用它。

    我打开了一个拉取请求:https://github.com/FriendsOfSymfony/FOSElasticaBundle/pull/748

    我们拭目以待!如果这只能帮助一个人,我已经很高兴了!

    【讨论】:

    • 如何在3.2.2 版本上使用它?
    【解决方案3】:

    同时,您可以将索引实例作为服务获取 (fos_elastica.index.INDEX_NAME.TYPE_NAME) 并请求 count() 方法。

    【讨论】:

      猜你喜欢
      • 2014-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多