b2pweb / bdf-prime-indexer
Prime 的索引插件
2.0.0
2024-02-26 14:13 UTC
Requires
- php: ~7.4 | ~8.0.0 | ~8.1.0 | ~8.2.0 | ~8.3.0
- b2pweb/bdf-collections: ^1.1.4
- b2pweb/bdf-prime: ~2.0
- elasticsearch/elasticsearch: ~7.0|~8.0
Requires (Dev)
- b2pweb/bdf-prime-bundle: ~1.0
- phpunit/phpunit: ~9.0
- squizlabs/php_codesniffer: ~3.0
- symfony/console: ~4.0|~5.0
- symfony/framework-bundle: ~4.0|~5.0
- symfony/messenger: ~4.0|~5.0
- symfony/yaml: ~4.0|~5.0
- vimeo/psalm: ~4.7
This package is auto-updated.
Last update: 2024-09-05 12:23:25 UTC
README
通过 Prime 索引实体,并从 Elasticsearch 索引中请求数据。
安装
使用 composer 安装
composer require b2pweb/bdf-prime-indexer
在 config/bundles.php
中注册
<?php return [ // ... Bdf\Prime\Indexer\Bundle\PrimeIndexerBundle::class => ['all' => true], Bdf\PrimeBundle\PrimeBundle::class => ['all' => true], ];
在 config/packages/prime_indexer.yaml
中配置索引
prime_indexer: elasticsearch: # Define elasticsearch hosts hosts: ['127.0.0.1:9222'] # Define indexes in form [Entity class]: [Index configuration class] # This is not mandatory if autoconfiguration is enabled indexes: App\Entities\City: App\Entities\CityIndex App\Entities\User: App\Entities\UserIndex
使用
声明索引
要声明索引,您首先需要声明配置
<?php class CityIndex implements ElasticsearchIndexConfigurationInterface { // Declare the index name public function index(): string { return 'test_cities'; } // Get the mapped entity type public function entity(): string { return City::class; } // Build properties public function properties(PropertiesBuilder $builder): void { $builder ->string('name') ->integer('population') ->string('zipCode') ->string('country')->notAnalyzed() ->boolean('enabled') ; } // The id accessor public function id(): ?PropertyAccessorInterface { return new SimplePropertyAccessor('id'); } // Declare analyzers public function analyzers(): array { return [ 'default' => [ 'type' => 'custom', 'tokenizer' => 'standard', 'filter' => ['lowercase', 'asciifolding'], ], ]; } // Scopes public function scopes(): array { return [ // "default" scope is always applied to the query 'default' => function (ElasticsearchQuery $query) { $query ->wrap( (new FunctionScoreQuery()) ->addFunction('field_value_factor', [ 'field' => 'population', 'factor' => 1, 'modifier' => 'log1p' ]) ->scoreMode('multiply') ) ->filter('enabled', true) ; }, // Other scope : can be used as custom filter on query // Or using $index->myScope() 'matchName' => function (ElasticsearchQuery $query, string $name) { $query ->where(new Match('name', $name)) ->orWhere( (new QueryString($name.'%')) ->and() ->defaultField('name') ->analyzeWildcard() ->useLikeSyntax() ) ; } ]; } }
可以通过实现接口添加一些额外配置
CustomEntitiesConfigurationInterface
:用于定义实体加载方法ShouldBeIndexedConfigurationInterface
:用于定义判断实体是否应该被索引的谓词
之后,可以将索引添加到 "prime_indexer.indexes" 配置中,或者让自动配置完成工作。
查询索引
查询系统使用 Prime 接口,所以用法几乎相同
<?php // Get the City index $index = $container->get(\Bdf\Prime\Indexer\IndexFactory::class)->for(City::class); // Get the query $query = $index->query(); $query ->where('country', 'FR') // Simple where works as expected ->where('name', ':like', 'P%') // "like" operator is supported ->orWhere(new QueryString('my complete query')) // Operator object can be used for more powerful filters ; // Get all cities who match with filters $query->all(); // First returns the first matching element, wrapped into an Optional $query->first()->get(); // Get the raw result of the elasticsearch query $query->execute(); // Use scope directly $index->matchName('Paris')->all(); // Same as above, but with scope as filter $index->query()->where('matchName', 'Paris')->all();
更新索引
可以手动在索引上执行更新操作
<?php // Get the City index $index = $container->get(\Bdf\Prime\Indexer\IndexFactory::class)->for(City::class); // Create the index, and insert all cities from database $index->create(City::walk()); $paris = new City([ 'name' => 'Paris', 'population' => 2201578, 'country' => 'FR', 'zipCode' => '75000' ]); // Indexing the city $index->add($paris); // The "id" property is filled after insertion echo $paris->id(); // Make sure that index is up to date // !!! Do not use on production !!! $index->refresh(); $index->contains($paris); // true // Update one attribute $paris->setPopulation(2201984); $index->update($paris, ['population']); // Remove the entity $index->remove($paris); $index->contains($paris); // false // Drop index $index->drop();
使用 CLI
创建索引并索引实体
bin/console.php prime:indexer:create App\Entities\City
将显示进度条以跟踪索引进度。
注意:实体的完全限定类名必须用作参数。
用于管理 Elasticsearch 索引
bin/console.php elasticsearch:show
bin/console.php elasticsearch:delete test_cities
测试
因为测试是更重要的事情之一,为此添加了一个实用程序类
注意:索引名称将前缀为 "test_" 以确保它不会影响真实索引。
<?php class MyTest extends \Bdf\PHPUnit\WebTestCase { /** * @var TestingIndexer */ private $indexTester; protected function setUp(): void { parent::setUp(); $this->indexTester = new TestingIndexer($this->app); $this->indexTester->index(City::class); // Declare the city index } protected function tearDown() : void { parent::tearDown(); $this->indexTester->destroy(); } public function test_city_index() { // Push entities to index $this->indexTester->push([ new City(...), new City(...), new City(...), ]); // Remove from index $this->indexTester->remove(new City(...)); // Querying to the index $query = $this->indexTester->index(City::class)->query(); } }
与 Prime 的交互和差异
- 使用索引系统不需要注册 Prime。一些实体可以进入索引,但不在数据库中。
- 与 Prime 不同,映射是面向索引而不是面向模型
- PropertiesBuilder 定义索引属性,并将其映射到模型属性
- 允许计算属性(即未存储在实体中的属性)
- 查询过滤器列未映射,并使用索引的列
- 查询使用流(来自 b2pweb/bdf-collections),因此 first() 返回 OptionalInterface,并且转换是在流上完成的