Getting Started#
Lets get started with the Search Engine Abstraction Layer library for PHP.
In this part we will show how you can start using SEAL in your project and its basic functions.
Installation#
To install the package you need to use Composer as the packages are registered there.
Depending on your project you can decide to use already existing Framework
integration of the package or the Standalone
version.
If you want to use standalone version use the following package:
composer require cmsig/seal
If you are using Laravel use the following packages:
composer require cmsig/seal-laravel-package
If you are using Symfony use the following packages:
composer require cmsig/seal-symfony-bundle
If you are using Spiral use the following packages:
composer require cmsig/seal-spiral-bridge
If you are using Mezzio use the following packages:
composer require cmsig/seal-mezzio-module
If you are using Yii use the following packages:
composer require cmsig/seal-yii-module
Install the Meilisearch adapter:
composer require cmsig/seal-meilisearch-adapter
Install the Algolia adapter:
composer require cmsig/seal-algolia-adapter
Install the Elasticsearch adapter:
composer require cmsig/seal-elasticsearch-adapter
Install the Opensearch adapter:
composer require cmsig/seal-opensearch-adapter
Install the Redisearch adapter:
composer require cmsig/seal-redisearch-adapter
Install the Loupe adapter:
composer require cmsig/seal-loupe-adapter
Install the Solr adapter:
composer require cmsig/seal-solr-adapter
Install the Typesense adapter:
composer require cmsig/seal-typesense-adapter
Configure Schema#
The Schema
defines the different Indexes
and their Fields
.
The definition of the fields depends on which data you want to store (text, int, float, …) in the search engine
and what you want todo with it later (searchable, filterable, sortable, …).
In this section we will create a first schema for our Index
:
When using the Standalone
version you need to create a new Index
instance as part of the Schema
:
<?php
use CmsIg\Seal\Schema\Field;
use CmsIg\Seal\Schema\Index;
use CmsIg\Seal\Schema\Schema;
$schema = new Schema([
'blog' => new Index('blog', [
'id' => new Field\IdentifierField('id'),
'title' => new Field\TextField('title'),
'description' => new Field\TextField('description'),
'tags' => new Field\TextField('tags', multiple: true, filterable: true),
]),
]);
If you are using Laravel create a new Index
in the resources/schemas
directory:
<?php // resources/schemas/blog.php
use CmsIg\Seal\Schema\Field;
use CmsIg\Seal\Schema\Index;
return new Index('blog', [
'id' => new Field\IdentifierField('id'),
'title' => new Field\TextField('title'),
'description' => new Field\TextField('description'),
'tags' => new Field\TextField('tags', multiple: true, filterable: true),
]);
If you are using Symfony create a new Index
in the resources/schemas
directory:
<?php // config/schemas/blog.php
use CmsIg\Seal\Schema\Field;
use CmsIg\Seal\Schema\Index;
return new Index('blog', [
'id' => new Field\IdentifierField('id'),
'title' => new Field\TextField('title'),
'description' => new Field\TextField('description'),
'tags' => new Field\TextField('tags', multiple: true, filterable: true),
]);
If you are using Spiral create a new Index
in the resources/schemas
directory:
<?php // app/schemas/blog.php
use CmsIg\Seal\Schema\Field;
use CmsIg\Seal\Schema\Index;
return new Index('blog', [
'id' => new Field\IdentifierField('id'),
'title' => new Field\TextField('title'),
'description' => new Field\TextField('description'),
'tags' => new Field\TextField('tags', multiple: true, filterable: true),
]);
If you are using Mezzio create a new Index
in the config/schemas
directory:
<?php // config/schemas/blog.php
use CmsIg\Seal\Schema\Field;
use CmsIg\Seal\Schema\Index;
return new Index('blog', [
'id' => new Field\IdentifierField('id'),
'title' => new Field\TextField('title'),
'description' => new Field\TextField('description'),
'tags' => new Field\TextField('tags', multiple: true, filterable: true),
]);
If you are using Yii create a new Index
in the config/schemas
directory:
<?php // config/schemas/blog.php
use CmsIg\Seal\Schema\Field;
use CmsIg\Seal\Schema\Index;
return new Index('blog', [
'id' => new Field\IdentifierField('id'),
'title' => new Field\TextField('title'),
'description' => new Field\TextField('description'),
'tags' => new Field\TextField('tags', multiple: true, filterable: true),
]);
For a full list of available fields see the Schema documentation. The
only required field is the IdentifierField
which can appear only once per index.
Configure Engine#
In the next step we will create the engine which will be use our created Schema
.
The Engine
is the main class which will be used to communicate with the search engine.
So for all kind of operations like add, remove, search, filter, drop, create, … we need to use the Engine
.
It requires an instance of the Adapter
which we did install before to connect to the correct Search engine.
When using the Standalone
version we need to create a new instance of Engine
class to create it. The Engine
requires beside the already created Schema
also
an instance of Adapter
which will be used to communicate with the search engine.
Use the following code to create a new Engine
using the Meilisearch
adapter:
<?php
use Meilisearch\Client;
use CmsIg\Seal\Adapter\Meilisearch\MeilisearchAdapter;
use CmsIg\Seal\Engine;
$client = new Client('http://127.0.0.1:7700');
$engine = new Engine(
new MeilisearchAdapter($client),
$schema,
);
Use the following code to create a new Engine
using the Algolia
adapter:
<?php
use Algolia\AlgoliaSearch\SearchClient;
use CmsIg\Seal\Adapter\Algolia\AlgoliaAdapter;
use CmsIg\Seal\Engine;
$client = Algolia\AlgoliaSearch\SearchClient::create(
'YourApplicationID',
'YourAdminAPIKey',
);
$engine = new Engine(
new AlgoliaAdapter($client),
$schema,
);
Use the following code to create a new Engine
using the Elasticsearch
adapter:
<?php
use Elastic\Elasticsearch\ClientBuilder;
use CmsIg\Seal\Adapter\Elasticsearch\ElasticsearchAdapter;
use CmsIg\Seal\Engine;
$client = ClientBuilder::create()->setHosts([
'127.0.0.1:9200'
])->build()
$engine = new Engine(
new ElasticsearchAdapter($client),
$schema,
);
Use the following code to create a new Engine
using the Opensearch
adapter:
<?php
use OpenSearch\ClientBuilder;
use CmsIg\Seal\Adapter\Opensearch\OpensearchAdapter;
use CmsIg\Seal\Engine;
$client = ClientBuilder::create()->setHosts([
'127.0.0.1:9200'
])->build()
$engine = new Engine(
new OpensearchAdapter($client),
$schema,
);
Use the following code to create a new Engine
using the Redisearch
adapter:
<?php
use Redis;
use CmsIg\Seal\Adapter\RediSearch\RediSearchAdapter;
use CmsIg\Seal\Engine;
$redis = new Redis([
'host' => '127.0.0.1',
'port' => 6379,
'auth' => ['phpredis', 'phpredis'],
]);
$engine = new Engine(
new RediSearchAdapter($redis),
$schema,
);
Use the following code to create a new Engine
using the Loupe
adapter:
<?php
use Loupe\Loupe\LoupeFactory;
use CmsIg\Seal\Adapter\Loupe\LoupeAdapter;
use CmsIg\Seal\Adapter\Loupe\LoupeHelper;
use CmsIg\Seal\Engine;
$loupeHelper = new LoupeHelper(
new LoupeFactory(),
$directory,
);
$engine = new Engine(
new LoupeAdapter($loupeHelper),
$schema,
);
Use the following code to create a new Engine
using the Solr
adapter:
<?php
use Solr\Client;
use Solarium\Core\Client\Adapter\Curl;
use CmsIg\Seal\Adapter\Solr\SolrAdapter;
use CmsIg\Seal\Engine;
use Symfony\Component\EventDispatcher\EventDispatcher;
$client = new Client(new Curl(), new EventDispatcher(), [
'endpoint' => [
'localhost' => [
'host' => '127.0.0.1',
'port' => '8983',
// authenticated required for configset api https://solr.apache.org/guide/8_9/configsets-api.html
// alternative set solr.disableConfigSetsCreateAuthChecks=true in your server setup
'username' => 'solr',
'password' => 'SolrRocks',
],
]
]);
$engine = new Engine(
new SolrAdapter($client),
$schema,
);
Use the following code to create a new Engine
using the Typesense
adapter:
<?php
use Http\Client\Curl\Client as CurlClient;
use Http\Discovery\Psr17FactoryDiscovery;
use CmsIg\Seal\Adapter\Typesense\TypesenseAdapter;
use CmsIg\Seal\Engine;
use Typesense\Client;
$client = new Client(
[
'api_key' => 'S3CR3T',
'nodes' => [
[
'host' => '127.0.0.1',
'port' => '8108',
'protocol' => 'http',
],
],
'client' => new CurlClient(Psr17FactoryDiscovery::findResponseFactory(), Psr17FactoryDiscovery::findStreamFactory()),
]
);
$engine = new Engine(
new TypesenseAdapter($client),
$schema,
);
When we are using the Laravel integration package we just need to configure our Engine
in the config/cmsig_seal.php
file. The Adapter
is configured via a DSN
like string.
Use the following configuration to use Meilisearch
as your default Engine
adapter:
<?php // config/cmsig_seal.php
return [
'schemas' => [
'default' => [
'dir' => resource_path('schemas'),
],
],
'engines' => [
'default' => [
'adapter' => 'meilisearch://127.0.0.1:7700',
],
],
];
Use the following configuration to use Algolia
as your default Engine
adapter:
<?php // config/cmsig_seal.php
return [
'schemas' => [
'default' => [
'dir' => resource_path('schemas'),
],
],
'engines' => [
'default' => [
'adapter' => 'algolia://' . env('ALGOLIA_APPLICATION_ID') . ':' . env('ALGOLIA_ADMIN_API_KEY'),
],
],
];
Use the following configuration to use Elasticsearch
as your default Engine
adapter:
<?php // config/cmsig_seal.php
return [
'schemas' => [
'default' => [
'dir' => resource_path('schemas'),
],
],
'engines' => [
'default' => [
'adapter' => 'elasticsearch://127.0.0.1:9200',
],
],
];
Use the following configuration to use Opensearch
as your default Engine
adapter:
<?php // config/cmsig_seal.php
return [
'schemas' => [
'default' => [
'dir' => resource_path('schemas'),
],
],
'engines' => [
'default' => [
'adapter' => 'opensearch://127.0.0.1:9200',
],
],
];
Use the following configuration to use Redisearch
as your default Engine
adapter:
<?php // config/cmsig_seal.php
return [
'schemas' => [
'default' => [
'dir' => resource_path('schemas'),
],
],
'engines' => [
'default' => [
'adapter' => 'redis://127.0.0.1:6379',
],
],
];
Use the following configuration to use Loupe
as your default Engine
adapter:
<?php // config/cmsig_seal.php
return [
'schemas' => [
'default' => [
'dir' => resource_path('schemas'),
],
],
'engines' => [
'default' => [
'adapter' => 'loupe://var/indexes',
],
],
];
Use the following configuration to use Solr
as your default Engine
adapter:
<?php // config/cmsig_seal.php
return [
'schemas' => [
'default' => [
'dir' => resource_path('schemas'),
],
],
'engines' => [
'default' => [
'adapter' => 'solr://127.0.0.1:8983',
],
],
];
Use the following configuration to use Typesense
as your default Engine
adapter:
<?php // config/cmsig_seal.php
return [
'schemas' => [
'default' => [
'dir' => resource_path('schemas'),
],
],
'engines' => [
'default' => [
'adapter' => 'typesense://S3CR3T@127.0.0.1:8108',
],
],
];
Note
The Laravel
integration provides also Facades for the later used default Engine
and EngineRegistry
. They are provided under the CmsIg\Seal\Integration\Laravel\Facade\
namespace. See also the Laravel Integration README.
When we are using the Symfony Bundle we just need to configure our Engine
in the config/packages/seal.yaml
file. The Adapter
is configured
via a DSN
like string.
Use the following configuration to use Meilisearch
as your default Engine
adapter:
# config/packages/seal.yaml
cmsig_seal:
schemas:
default:
dir: '%kernel.project_dir%/config/schemas'
engines:
default:
adapter: 'meilisearch://127.0.0.1:7700'
Use the following configuration to use Algolia
as your default Engine
adapter:
# config/packages/seal.yaml
cmsig_seal:
schemas:
default:
dir: '%kernel.project_dir%/config/schemas'
engines:
default:
adapter: 'algolia://%env(ALGOLIA_APPLICATION_ID)%:%env(ALGOLIA_ADMIN_API_KEY)%'
Use the following configuration to use Elasticsearch
as your default Engine
adapter:
# config/packages/seal.yaml
cmsig_seal:
schemas:
default:
dir: '%kernel.project_dir%/config/schemas'
engines:
default:
adapter: 'elasticsearch://127.0.0.1:9200'
Use the following configuration to use Opensearch
as your default Engine
adapter:
# config/packages/seal.yaml
cmsig_seal:
schemas:
default:
dir: '%kernel.project_dir%/config/schemas'
engines:
default:
adapter: 'opensearch://127.0.0.1:9200'
Use the following configuration to use Redisearch
as your default Engine
adapter:
# config/packages/seal.yaml
cmsig_seal:
schemas:
default:
dir: '%kernel.project_dir%/config/schemas'
engines:
default:
adapter: 'redis://127.0.0.1:6379'
Use the following configuration to use Loupe
as your default Engine
adapter:
# config/packages/seal.yaml
cmsig_seal:
schemas:
default:
dir: '%kernel.project_dir%/config/schemas'
engines:
default:
adapter: 'loupe://var/indexes'
Use the following configuration to use Solr
as your default Engine
adapter:
# config/packages/seal.yaml
cmsig_seal:
schemas:
default:
dir: '%kernel.project_dir%/config/schemas'
engines:
default:
adapter: 'solr://127.0.0.1:8983'
Use the following configuration to use Typesense
as your default Engine
adapter:
# config/packages/seal.yaml
cmsig_seal:
schemas:
default:
dir: '%kernel.project_dir%/config/schemas'
engines:
default:
adapter: 'typesense://S3CR3T@127.0.0.1:8108'
When we are using the Spiral integration package we just need to configure our Engine
in the app/config/cmsig_seal.php
file. The Adapter
is configured via a DSN
like string.
Use the following configuration to use Meilisearch
as your default Engine
adapter:
<?php // app/config/cmsig_seal.php
return [
'schemas' => [
'default' => [
'dir' => resource_path('schemas'),
],
],
'engines' => [
'default' => [
'adapter' => 'meilisearch://127.0.0.1:7700',
],
],
];
Use the following configuration to use Algolia
as your default Engine
adapter:
<?php // app/config/cmsig_seal.php
return [
'schemas' => [
'default' => [
'dir' => resource_path('schemas'),
],
],
'engines' => [
'default' => [
'adapter' => 'algolia://' . env('ALGOLIA_APPLICATION_ID') . ':' . env('ALGOLIA_ADMIN_API_KEY'),
],
],
];
Use the following configuration to use Elasticsearch
as your default Engine
adapter:
<?php // app/config/cmsig_seal.php
return [
'schemas' => [
'default' => [
'dir' => resource_path('schemas'),
],
],
'engines' => [
'default' => [
'adapter' => 'elasticsearch://127.0.0.1:9200',
],
],
];
Use the following configuration to use Opensearch
as your default Engine
adapter:
<?php // app/config/cmsig_seal.php
return [
'schemas' => [
'default' => [
'dir' => resource_path('schemas'),
],
],
'engines' => [
'default' => [
'adapter' => 'opensearch://127.0.0.1:9200',
],
],
];
Use the following configuration to use Redisearch
as your default Engine
adapter:
<?php // app/config/cmsig_seal.php
return [
'schemas' => [
'default' => [
'dir' => resource_path('schemas'),
],
],
'engines' => [
'default' => [
'adapter' => 'redis://127.0.0.1:6379',
],
],
];
Use the following configuration to use Loupe
as your default Engine
adapter:
<?php // app/config/cmsig_seal.php
return [
'schemas' => [
'default' => [
'dir' => resource_path('schemas'),
],
],
'engines' => [
'default' => [
'adapter' => 'loupe://var/indexes',
],
],
];
Use the following configuration to use Solr
as your default Engine
adapter:
<?php // app/config/cmsig_seal.php
return [
'schemas' => [
'default' => [
'dir' => resource_path('schemas'),
],
],
'engines' => [
'default' => [
'adapter' => 'solr://127.0.0.1:8983',
],
],
];
Use the following configuration to use Typesense
as your default Engine
adapter:
<?php // app/config/cmsig_seal.php
return [
'schemas' => [
'default' => [
'dir' => resource_path('schemas'),
],
],
'engines' => [
'default' => [
'adapter' => 'typesense://S3CR3T@127.0.0.1:8108',
],
],
];
When we are using the Mezzio integration package we just need to configure our Engine
in the src/App/src/ConfigProvider.php
file. The Adapter
is configured via a DSN
like string.
Use the following configuration to use Meilisearch
as your default Engine
adapter:
<?php // src/App/src/ConfigProvider.php
class ConfigProvider
{
public function __invoke(): array
{
return [
// ...
'cms_seal' => [
'schemas' => [
'default' => [
'dir' => 'config/schemas',
],
],
'engines' => [
'default' => [
'adapter' => 'meilisearch://127.0.0.1:7700',
],
],
],
];
}
}
Use the following configuration to use Algolia
as your default Engine
adapter:
<?php // src/App/src/ConfigProvider.php
class ConfigProvider
{
public function __invoke(): array
{
return [
// ...
'cmsig_seal' => [
'schemas' => [
'default' => [
'dir' => 'config/schemas',
],
],
'engines' => [
'default' => [
'adapter' => 'algolia://' . \getenv('ALGOLIA_APPLICATION_ID') . ':' . \getenv('ALGOLIA_ADMIN_API_KEY'),
],
],
],
];
}
}
Use the following configuration to use Elasticsearch
as your default Engine
adapter:
<?php // src/App/src/ConfigProvider.php
class ConfigProvider
{
public function __invoke(): array
{
return [
// ...
'cmsig_seal' => [
'schemas' => [
'default' => [
'dir' => 'config/schemas',
],
],
'engines' => [
'default' => [
'adapter' => 'elasticsearch://127.0.0.1:9200',
],
],
],
];
}
}
Use the following configuration to use Opensearch
as your default Engine
adapter:
<?php // src/App/src/ConfigProvider.php
class ConfigProvider
{
public function __invoke(): array
{
return [
// ...
'cmsig_seal' => [
'schemas' => [
'default' => [
'dir' => 'config/schemas',
],
],
'engines' => [
'default' => [
'adapter' => 'opensearch://127.0.0.1:9200',
],
],
],
];
}
}
Use the following configuration to use Redisearch
as your default Engine
adapter:
<?php // src/App/src/ConfigProvider.php
class ConfigProvider
{
public function __invoke(): array
{
return [
// ...
'cmsig_seal' => [
'schemas' => [
'default' => [
'dir' => 'config/schemas',
],
],
'engines' => [
'default' => [
'adapter' => 'redis://127.0.0.1:6379',
],
],
],
];
}
}
Use the following configuration to use Loupe
as your default Engine
adapter:
<?php // src/App/src/ConfigProvider.php
class ConfigProvider
{
public function __invoke(): array
{
return [
// ...
'cmsig_seal' => [
'schemas' => [
'default' => [
'dir' => 'config/schemas',
],
],
'engines' => [
'default' => [
'adapter' => 'loupe://var/indexes',
],
],
],
];
}
}
Use the following configuration to use Solr
as your default Engine
adapter:
<?php // src/App/src/ConfigProvider.php
class ConfigProvider
{
public function __invoke(): array
{
return [
// ...
'cmsig_seal' => [
'schemas' => [
'default' => [
'dir' => 'config/schemas',
],
],
'engines' => [
'default' => [
'adapter' => 'solr://127.0.0.1:8983',
],
],
],
];
}
}
Use the following configuration to use Typesense
as your default Engine
adapter:
<?php // src/App/src/ConfigProvider.php
class ConfigProvider
{
public function __invoke(): array
{
return [
// ...
'cmsig_seal' => [
'schemas' => [
'default' => [
'dir' => 'config/schemas',
],
],
'engines' => [
'default' => [
'adapter' => 'typesense://S3CR3T@127.0.0.1:8108',
],
],
],
];
}
}
When we are using the Yii integration package we just need to configure our Engine
in the config/common/params.php
file. The Adapter
is configured via a DSN
like string.
Use the following configuration to use Meilisearch
as your default Engine
adapter:
<?php // config/common/params.php
return [
// ...
'cmsig/seal-yii-module' => [
'schemas' => [
'default' => [
'dir' => 'config/schemas',
],
],
'engines' => [
'default' => [
'adapter' => 'meilisearch://127.0.0.1:7700',
],
],
],
];
Use the following configuration to use Algolia
as your default Engine
adapter:
<?php // config/common/params.php
return [
// ...
'cmsig/seal-yii-module' => [
'schemas' => [
'default' => [
'dir' => 'config/schemas',
],
],
'engines' => [
'default' => [
'adapter' => 'algolia://' . \getenv('ALGOLIA_APPLICATION_ID') . ':' . \getenv('ALGOLIA_ADMIN_API_KEY'),
],
],
],
];
Use the following configuration to use Elasticsearch
as your default Engine
adapter:
<?php // config/common/params.php
return [
// ...
'cmsig/seal-yii-module' => [
'schemas' => [
'default' => [
'dir' => 'config/schemas',
],
],
'engines' => [
'default' => [
'adapter' => 'elasticsearch://127.0.0.1:9200',
],
],
],
];
Use the following configuration to use Opensearch
as your default Engine
adapter:
<?php // config/common/params.php
return [
// ...
'cmsig/seal-yii-module' => [
'schemas' => [
'default' => [
'dir' => 'config/schemas',
],
],
'engines' => [
'default' => [
'adapter' => 'opensearch://127.0.0.1:9200',
],
],
],
];
Use the following configuration to use Redisearch
as your default Engine
adapter:
<?php // config/common/params.php
return [
// ...
'cmsig/seal-yii-module' => [
'schemas' => [
'default' => [
'dir' => 'config/schemas',
],
],
'engines' => [
'default' => [
'adapter' => 'redis://127.0.0.1:6379',
],
],
],
];
Use the following configuration to use Loupe
as your default Engine
adapter:
<?php // config/common/params.php
return [
// ...
'cmsig/seal-yii-module' => [
'schemas' => [
'default' => [
'dir' => 'config/schemas',
],
],
'engines' => [
'default' => [
'adapter' => 'loupe://var/indexes',
],
],
],
];
Use the following configuration to use Solr
as your default Engine
adapter:
<?php // config/common/params.php
return [
// ...
'cmsig/seal-yii-module' => [
'schemas' => [
'default' => [
'dir' => 'config/schemas',
],
],
'engines' => [
'default' => [
'adapter' => 'solr://127.0.0.1:8983',
],
],
],
];
Use the following configuration to use Typesense
as your default Engine
adapter:
<?php // config/common/params.php
return [
// ...
'cmsig/seal-yii-module' => [
'schemas' => [
'default' => [
'dir' => 'config/schemas',
],
],
'engines' => [
'default' => [
'adapter' => 'typesense://S3CR3T@127.0.0.1:8108',
],
],
],
];
Prepare Search Engine#
If you already have your search engine running you can skip this step. Still we want to provide here different docker-compose files to get you started quickly with your favorite search engine.
A instance of Meilisearch can be started with the following docker-compose file:
# docker-compose.yml
services:
meilisearch:
image: getmeili/meilisearch:v1
environment:
MEILI_ENV: development
ports:
- "7700:7700"
healthcheck:
test: ["CMD-SHELL", "curl --silent --fail localhost:7700/health || exit 1"]
interval: 5s
timeout: 5s
retries: 20
volumes:
- meilisearch-data:/data.ms
volumes:
meilisearch-data:
To start the search engine run the following command:
docker-compose up
Depending on the service after a few seconds up to a minute the service is ready to use. And you can continue with the next step.
As Algolia is SaaS, there is nothing to run it required. You can create a free account
at https://www.algolia.com/users/sign_up.
After Signup you will get an ALGOLIA_APPLICATION_ID
and an ALGOLIA_ADMIN_API_KEY
.
Which you need to configure that your engine adapter configuration will then use them like
above.
A instance of Elasticsearch can be started with the following docker-compose file:
# docker-compose.yml
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.15.3
environment:
discovery.type: single-node
xpack.security.enabled: 'false'
cluster.routing.allocation.disk.threshold_enabled: 'false'
ports:
- "9200:9200"
healthcheck:
test: ["CMD-SHELL", "curl --silent --fail localhost:9200/_cluster/health || exit 1"]
interval: 5s
timeout: 5s
retries: 20
volumes:
- elasticsearch-data:/usr/share/elasticsearch/data
volumes:
elasticsearch-data:
To start the search engine run the following command:
docker-compose up
Depending on the service after a few seconds up to a minute the service is ready to use. And you can continue with the next step.
A instance of Opensearch can be started with the following docker-compose file:
# docker-compose.yml
services:
opensearch:
image: opensearchproject/opensearch:2
environment:
discovery.type: single-node
cluster.routing.allocation.disk.threshold_enabled: 'false'
DISABLE_SECURITY_PLUGIN: true
ports:
- "9200:9200"
healthcheck:
test: ["CMD-SHELL", "curl --silent --fail localhost:9200/_cluster/health || exit 1"]
interval: 5s
timeout: 5s
retries: 20
volumes:
- opensearch-data:/usr/share/opensearch/data
volumes:
opensearch-data:
To start the search engine run the following command:
docker-compose up
Depending on the service after a few seconds up to a minute the service is ready to use. And you can continue with the next step.
A instance of Redisearch can be started with the following docker-compose file.
The here used redis/redis-stack image contains the required Redisearch
and JSON
modules to run the search engine:
# docker-compose.yml
services:
redis:
image: redis/redis-stack:7.4.0-v1
ports:
- 6379:6379 # redis server
- 8001:8001 # redis insight
environment:
REDIS_ARGS: --requirepass supersecure
volumes:
- redisearch-data:/data
volumes:
redisearch-data:
To start the search engine run the following command:
docker-compose up
Depending on the service after a few seconds up to a minute the service is ready to use. And you can continue with the next step.
As Loupe is PHP based build on top of SQLite, there is no service other service required to use it. You just need to make sure that you have the required sqlite php extension <https://www.php.net/pdo_sqlite>`__ installed. The php package manager composer should already tell you if you are missing the extension.
A instance of Solr can be started with the following docker-compose file. It uses the required cloud mode to run the search engine. Running it without cloud mode is not supported yet:
# docker-compose.yml
services:
solr:
image: "solr:9"
ports:
- "8983:8983"
- "9983:9983"
command: solr -f -cloud
healthcheck:
test: ["CMD-SHELL", "curl --silent --fail localhost:8983 || exit 1"]
interval: 5s
timeout: 5s
retries: 20
environment:
SOLR_OPTS: '-Dsolr.disableConfigSetsCreateAuthChecks=true'
volumes:
- solr-data:/var/solr
zookeeper:
image: "solr:9"
depends_on:
- "solr"
network_mode: "service:solr"
environment:
SOLR_OPTS: '-Dsolr.disableConfigSetsCreateAuthChecks=true'
command: bash -c "set -x; export; wait-for-solr.sh; solr zk -z localhost:9983 upconfig -n default -d /opt/solr/server/solr/configsets/_default; tail -f /dev/null"
volumes:
solr-data:
To start the search engine run the following command:
docker-compose up
Depending on the service after a few seconds up to a minute the service is ready to use. And you can continue with the next step.
A instance of Typesense can be started with the following docker-compose file:
# docker-compose.yml
services:
typesense:
image: typesense/typesense:27.1
ports:
- "8108:8108"
environment:
TYPESENSE_DATA_DIR: /data
TYPESENSE_API_KEY: S3CR3T
healthcheck:
test: ["CMD-SHELL", "exit 0"] # TODO currently not working as curl not available: https://github.com/typesense/typesense/issues/441#issuecomment-1383157680
interval: 5s
timeout: 5s
retries: 20
volumes:
- typesense-data:/data
volumes:
typesense-data:
To start the search engine run the following command:
docker-compose up
Depending on the service after a few seconds up to a minute the service is ready to use. And you can continue with the next step.
Create Indexes#
Before you can use the search engine you need to create the indexes.
When using the Standalone
version you need to create the Indexes
in your search engines via the Engine
instance which was created before:
<?php
// create all indexes
$engine->createSchema();
// create specific index
$engine->createIndex('blog');
To create the indexes in Laravel the following artisan command:
# create all indexes
php artisan cmsig:seal:index-create
# create specific index
php artisan cmsig:seal:index-create --index=blog
To create the indexes in Symfony the following console command:
# create all indexes
bin/console cmsig:seal:index-create
# create specific index
bin/console cmsig:seal:index-create --index=blog
To create the indexes in Spiral the following command:
# create all indexes
php app.php cmsig:seal:index-create
# create specific index
php app.php cmsig:seal:index-create --index=blog
To create the indexes in Mezzio the following command:
# create all indexes
vendor/bin/laminas cmsig:seal:index-create
# create specific index
vendor/bin/laminas cmsig:seal:index-create --index=blog
To create the indexes in Yii the following command:
# create all indexes
./yii cmsig:seal:index-create
# create specific index
./yii cmsig:seal:index-create --index=blog
Add or Update Documents#
A document in SEAL is a associative array following the structure of the defined Schema.
The only required field is the IdentifierField
of the Schema.
To add documents to the search engine you need to use the Engine
instance.
With the following code we can add our first documents to our created index:
<?php
class YourService {
public function __construct(
private readonly \Schranz\Search\EngineInterface $engine
) {
}
public function someMethod()
{
$this->engine->saveDocument('blog', [
'id' => 1,
'title' => 'My first blog post',
'description' => 'This is the description of my first blog post',
'tags' => ['UI', 'UX'],
]);
$this->engine->saveDocument('blog', [
'id' => 3,
'title' => 'My seconds blog post',
'content' => 'This is the description of my second blog post',
'tags' => ['Tech', 'UX'],
]);
$this->engine->saveDocument('blog', [
'id' => 3,
'title' => 'My third blog post',
'content' => 'This is the description of my third blog post',
'tags' => ['Tech', 'UI'],
]);
}
}
To update a document you can use the same saveDocument
method with the same identifier.
For all kind of indexing operations have a look at the Index Operations documentation.
Search Documents#
In this step we will now search for our documents via a search term. This way we
are calling a basic search with a given term to the configured search engine. And
get a result of all documents which match the search term (first
) and a total count how
many exists in the given index.
<?php
class YourService {
public function __construct(
private readonly \Schranz\Search\EngineInterface $engine
) {
}
public function someMethod()
{
$result = $this->engine->createSearchBuilder('blog')
->addFilter(new \CmsIg\Seal\Search\Condition\SearchCondition('first'))
->getResult();
foreach ($result as $document) {
// do something with the document
}
$total = $result->total();
}
}
For all kind of search and filters have a look at the Search & Filter Conditions documentation.
Filter Documents#
Not even searching but also filtering the documents are possible. In the following example
we will filter by the tags
field and get all documents which have the tag UI
.
<?php
class YourService {
public function __construct(
private readonly \Schranz\Search\EngineInterface $engine
) {
}
public function someMethod()
{
$result = $this->engine->createSearchBuilder('blog')
->addFilter(new \CmsIg\Seal\Search\Condition\EqualCondition('tags', 'UI'));
->getResult();
foreach ($result as $document) {
// do something with the document
}
$total = $result->total();
}
}
For all kind of search and filters have a look at the Search & Filter Conditions documentation.
Reindex Documents#
If you have changed the schema or need to index or reindex all your documents the reindex functionality can be used.
First you need to create a ReindexProvider
providing all your documents.
<?php
class BlogReindexProvider implements ReindexProviderInterface
{
public function total(): ?int
{
return 2;
}
public function provide(): \Generator
{
yield [
'id' => 1,
'title' => 'Title 1',
'description' => 'Description 1',
];
yield [
'id' => 2,
'title' => 'Title 2',
'description' => 'Description 2',
];
}
public static function getIndex(): string
{
return 'blog';
}
}
After that you can use the reindex
to index all documents:
When using the Standalone
version you need to reindex the documents
in your search engines via the Engine
instance which was created before:
<?php
$reindexProviders = [
new BlogReindexProvider(),
];
// reindex all indexes
$engine->reindex($reindexProviders);
// reindex specific index and drop data before
$engine->reindex($reindexProviders, 'blog', dropIndex: true);
In Laravel the new created ReindexProvider
need to be tagged correctly:
<?php // app/Providers/AppServiceProvider.php
namespace App\Providers;
class AppServiceProvider extends \Illuminate\Support\ServiceProvider
{
// ...
public function boot(): void
{
$this->app->singleton(\App\Search\BlogReindexProvider::class, fn () => new \App\Search\BlogReindexProvider());
$this->app->tag(\App\Search\BlogReindexProvider::class, 'cmsig_seal.reindex_provider');
}
}
After correctly tagging the ReindexProvider
with seal.reindex_provider
the
cmsig:seal:reindex
command can be used to index all documents:
# reindex all indexes
php artisan cmsig:seal:reindex
# reindex specific index and drop data before
php artisan cmsig:seal:reindex --index=blog --drop
In Symfony the autoconfigure
feature should already tag the new ReindexProvider
correctly
with the seal.reindex_provider
tag. If not you can tag it manually:
# config/services.yaml
services:
App\Search\BlogReindexProvider:
tags:
- { name: cmsig_seal.reindex_provider }
After correctly tagging the ReindexProvider
use the following command to index all documents:
# reindex all indexes
bin/console cmsig:seal:reindex
# reindex specific index and drop data before
bin/console cmsig:seal:reindex --index=blog --drop
In Spiral the new created ReindexProvider
need to be registered correctly as reindex provider:
<?php // app/config/cmsig_seal.php
return [
// ...
'reindex_providers' => [
\App\Search\BlogReindexProvider::class,
],
];
After correctly registering the ReindexProvider
use the following command to index all documents:
# reindex all indexes
php app.php cmsig:seal:reindex
# reindex specific index and drop data before
php app.php cmsig:seal:reindex --index=blog --drop
In Mezzio the new created ReindexProvider
need to be registered correctly as reindex provider:
<?php // src/App/src/ConfigProvider.php
class ConfigProvider
{
public function __invoke(): array
{
return [
// ...
'cmsig_seal' => [
// ...
'reindex_providers' => [
\App\Search\BlogReindexProvider::class,
],
],
];
}
public function getDependencies(): array
{
return [
// ...
'invokables' => [
\App\Search\BlogReindexProvider::class => \App\Search\BlogReindexProvider::class,
],
// ...
];
}
}
After correctly registering the ReindexProvider
use the following command to index all documents:
# reindex all indexes
vendor/bin/laminas cmsig:seal:reindex
# reindex specific index and drop data before
vendor/bin/laminas cmsig:seal:reindex --index=blog --drop
In Yii the new created ReindexProvider
need to be registered correctly as reindex provider:
<?php // config/common/params.php
return [
// ...
'cmsig/seal-yii-module' => [
// ...
'reindex_providers' => [
\App\Search\BlogReindexProvider::class,
],
],
];
After correctly registering the ReindexProvider
use the following command to index all documents:
# reindex all indexes
./yii cmsig:seal:reindex
# reindex specific index and drop data before
./yii cmsig:seal:reindex --index=blog --drop
Help needed?#
If you need any help or run into any error feel free to use the Github Discussions of the main repository to ask any questions. Or check there if somebody already solved the same problem.
Next Steps#
These were the basic steps to get started with the Search Engine Abstraction Layer (SEAL). In the next part of the documentation, we will delve deeper into the Schema and explore the various field definitions. After that, we will a short look at the Index Operations and then examine the different conditions of Search & Filter Conditions the abstraction provides.