doctrine/search

此包已被弃用且不再维护。未建议替代包。

ElasticSearch 和 Solr 实体映射库

v0.2 2016-11-17 17:48 UTC

This package is not auto-updated.

Last update: 2022-05-06 15:13:18 UTC


README

注意:该项目目前是一个原型。有关实际实现示例,请参阅 demo 文件夹。

支持的搜索引擎

功能

  • SearchManager
    • 可独立使用或混合配置使用
    • 可配置的搜索管理器支持聚合实体管理器
    • 通过搜索引擎适配器(如 Elastica)直接进行 API 调用
    • 通过批量操作将返回的 ID 转换为所需的填充对象
    • 支持事件管理器监听器以自定义实体处理
  • 通过 JMS Serializer 或简单的实体回调通过事件监听器进行索引
  • 使用 ObjectManager::getClassMetadata() 作为基础结构创建索引和数据类型的注解

#用法#

配置

以下示例显示了如何配置搜索管理器连接

$config = new Doctrine\Search\Configuration();
$config->setMetadataCacheImpl(new Doctrine\Common\Cache\ArrayCache());
$config->setEntitySerializer(
  new Doctrine\Search\Serializer\JMSSerializer(
    JMS\Serializer\SerializationContext::create()->setGroups('search')
  )
);

$eventManager = new Doctrine\Search\EventManager();
$eventManager->addListener($listener);

$searchManager = new Doctrine\Search\SearchManager(
  $config,
  new Doctrine\Search\ElasticSearch\Client(
    new Elastica\Client(array(
      array('host' => 'localhost', 'port' => '9200')
    )
  ),
  $eventManager
);

映射

以下示例显示了索引和类型生成的基本实体映射。映射可以通过构建脚本来渲染成适合自动生成索引和类型的格式(需要高级设置)。

<?php
namespace Entities;

use Doctrine\Search\Mapping\Annotations as MAP;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @MAP\ElasticSearchable(index="indexname", type="post", source=true)
 */
class Post
{
  /**
   * @ORM\Id
   * @ORM\GeneratedValue(strategy="AUTO")
   * @MAP\ElasticField(type="integer", includeInAll=false)
   */
  private $id;

  /**
   * @ORM\Column(type="string")
   * @MAP\ElasticField(type="string", includeInAll=true, boost=5.0)
   */
  private $title;

  /**
   * @ORM\Column(type="text")
   * @MAP\ElasticField(type="string", includeInAll=true)
   */
  private $content;

  /**
   * @MAP\ElasticField(name="tags", type="string", includeInAll=false, index="not_analyzed")
   */
  public function getTags() {
    return $this->tags->slice(0,3);
  }
}

索引

目前可以通过以下方式对文档进行序列化以进行索引。如果需要,可以使用与 ORM 一起使用的事件监听器,如下例所示。如果不需要事件监听器,则可以直接使用搜索管理器对实体进行持久化或删除。

<?php
namespace Entities\Listener;

use Doctrine\ORM\Event\LifecycleEventArgs;
use Entities\Behaviour\SearchableEntityInterface;

class SearchableListener implements
{
      protected function getSearchManager() {
            return $this->getDatabaseConnection('elasticsearch');
      }

      public function postPersist(LifecycleEventArgs $oArgs) {
            $oEntity = $oArgs->getEntity();
            if($oEntity instanceof SearchableEntityInterface) {
                $this->getSearchManager()->persist($oEntity);
          }
      }

    public function postRemove(LifecycleEventArgs $oArgs) {
        $oEntity = $oArgs->getEntity();
        if($oEntity instanceof SearchableEntityInterface) {
            $this->getSearchManager()->remove($oEntity);
        }
    }
}

CallbackSerializer

此方法仅期望实体上的 toArray() 方法,尽管可以根据需要进行配置。示例中建议的接口可以是任何您想要的接口,只要您的事件监听器可以识别需要持久化到搜索引擎的实体(请参阅上面的示例)。

...
use Entities\Behaviour\SearchableEntityInterface

class Post implements SearchableEntityInterface
{
  ...
  public function toArray() {
    return array(
      'id' => $this->id,
      'title' => $this->title,
      'content' => $this->content
      ...
    );
  }
}

JMS Serializer

您还可以使用 JMS Serializer 的高级序列化功能来自动处理序列化,如以下示例所示。

...
use JMS\Serializer\Annotation as JMS;
use Entities\Behaviour\SearchableEntityInterface

/**
 * @ORM\Entity
 * @MAP\ElasticSearchable(index="indexname", type="post", source=true)
 * @JMS\ExclusionPolicy("all")
 */
class Post implements SearchableEntityInterface
{
  ...
  /**
   * @ORM\Column(type="string")
   * @MAP\ElasticField(type="string", includeInAll=true, boost=5.0)
   * @JMS\Expose
   * @JMS\Groups({"public", "search"})
   */
  private $title;

  /**
   * @ORM\Column(type="text")
   * @MAP\ElasticField(type="string", includeInAll=true)
   * @JMS\Expose
   * @JMS\Groups({"public", "search"})
   */
  private $content;
  ...
}

AnnotationSerializer

尚不可用。

查询

可以通过以下方式通过搜索管理器执行查询。使用结果缓存的用法是指使用缓存进行填充查询。搜索引擎特定的适配器接口被神奇地暴露出来,因此在这个示例中,Elastica\Query::addSort 方法与 Doctrine\Search\Query 方法合并。因此,任何由搜索引擎客户端库支持的查询复杂性都受到支持。

$hydrationQuery = $entityManager->createQueryBuilder()
  ->select(array('p', 'field(p.id, :ids) as HIDDEN field'))
    ->from('Entities\Post', 'p')
    ->where('p.id IN (:ids)')
    ->orderBy('field')
    ->getQuery();

$query = $searchManager->createQuery()
  ->from('Entities\Post')
  ->searchWith(new Elastica\Query())
    ->hydrateWith($hydrationQuery)
    ->addSort('_score')
    ->setFrom(0)
    ->setLimit(10)
    ->getResult();

可以使用以下技术进行简单的存储库ID查询和Term搜索。反序列化独立于Doctrine\ORM进行,但根据注册的SerializerInterface,相同的模型被相应地填充。

$entity = $searchManager->getRepository('Entities\Post')->find($id);
$entity = $searchManager->getRepository('Entities\Post')->findOneBy(array($key => $term));