0

我在一个使用 FosElasticaBundle (@dev) 的 Symfony 2.5.6 项目中。

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

localhost:9200/_search?search_type=count

请注意“search_type=count” URL 参数。

这是示例查询:

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

结果包含正常的 JSON 响应,但在part中没有任何文档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() 方法)。但是来自存储库的服务......你知道的。

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

4

3 回答 3

2

我面临同样的挑战,从 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

然后在回购中使用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 开始工作。

于 2015-07-01T13:05:43.687 回答
1

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

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

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

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

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

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

我选择了另一条路径,我分叉了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;
}

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

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

走着瞧!如果这只能帮助一个人,我已经很高兴了!

于 2014-11-27T10:32:22.503 回答
1

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

于 2015-05-18T11:14:10.000 回答