lekarna / search
ElasticSearch 和 Solr 实体映射库
0.5.1
2022-08-29 11:52 UTC
Requires
- php: >=5.3.2
- doctrine/common: >=2.3.0
Requires (Dev)
- doctrine/orm: ~2.4
- phpunit/phpunit: ~4.2
Suggests
- ruflin/Elastica: Elastica version correlating to your ElasticSearch installation is required.
- symfony/yaml: If you want to use YAML Metadata Mapping Driver
This package is auto-updated.
Last update: 2024-08-29 05:19:01 UTC
README
注意:该项目目前是一个原型。有关实际实现示例,请参阅 demo
文件夹。
支持的搜索引擎
- ElasticSearch (功能支持)
- Solr (部分实现)
特性
- SearchManager
- 可作为独立使用或混合配置使用
- 可配置的搜索管理器支持聚合实体管理器
- 支持通过搜索引擎适配器(如Elastica)进行直接API调用
- 通过批量操作将返回的ID转换为所需的填充对象
- 支持事件管理器监听器以进行可定制的实体处理
- 支持通过事件监听器进行索引,通过JMS序列化器或简单的实体回调。
- 使用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
的高级序列化功能来自动处理序列化,根据示例中的注解进行。如果需要,可以使用JMS序列化器来替代。
... 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));