Skip to content

The bundle works like a bridge to integrate Elasticsearch in Symfony. It provides developer APIs and eco-system to work with Elasticsearch easily using dependency injection (DI).

License

Notifications You must be signed in to change notification settings

phoenix-venture/elasticsearch-bundle

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

40 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PhoenixElasticsearchBundle

The bundle works like a bridge to integrate Elasticsearch in Symfony. It provides developer APIs and eco-system to work with Elasticsearch easily using dependency injection (DI).

Features

  • Server status and information
  • Index management
  • Document management

Installation

  • Clone repository.
# https://github.com/hirenchhatbar/elasticsearch-bundle
git clone git@github.com:hirenchhatbar/elasticsearch-bundle.git vendor/phoenix/elasticsearch-bundle
  • Install dependencies.
# https://packagist.org/packages/elasticsearch/elasticsearch
composer require elasticsearch/elasticsearch
  • Autoload bundle with composer.json.
// composer.json
"autoload": {
    "psr-4": {
        "App\\": "src/",

        "Phoenix\\ElasticsearchBundle\\": "vendor/phoenix/elasticsearch-bundle/"
    }
},
  • Dump autoload with composer
composer dump-autoload
  • Add new bundle in config/bundles.php.
// config/bundles.php
return [
    Phoenix\ElasticsearchBundle\PhoenixElasticsearchBundle::class => ['all' => true],
]

Usage

Create index class and register it as service with 'es.index' tag:

// vendor/phoenix/api-bundle/Elasticsearch/Index/LocationIndex.php

<?php
/*
 * This file is part of the Phoenix package.
 *
 * (c) Hiren Chhatbar <hc.rajkot@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Phoenix\ApiBundle\Elasticsearch\Index;

use Phoenix\ElasticsearchBundle\Index\AbstractIndex;
use Phoenix\ApiBundle\Elasticsearch\Document\LocationDocument;

/**
 * Class LocationIndex
 *
 * @package Phoenix\ApiBundle\Index
 * @author Hiren Chhatbar
 */
class LocationIndex extends AbstractIndex
{
    /**
     * Holds name.
     *
     * @var string
     */
    public string $name = 'location';

    /**
     * Constructor.
     *
     * @param LocationDocument $document
     */
    public function __construct(LocationDocument $document)
    {
        $this->document = $document;
    }

    /**
     * {@inheritDoc}
     *
     * @see \Phoenix\ElasticsearchBundle\Index\AbstractIndex::settings()
     */
    public function settings(): array
    {
        $settings = $this->defaultSettings();

        return $settings;
    }

    /**
     * {@inheritDoc}
     *
     * @see \Phoenix\ElasticsearchBundle\Index\AbstractIndex::mappings()
     */
    public function mappings(): array
    {
        $defaultMappings = $this->defaultMappings();

        $mappings = [
            'properties' => [
                'parent' => [
                    'type' => 'integer',
                ],
                'name' => [
                    'type' => 'keyword',
                ],
                'path' => [
                    'type' => 'keyword',
                ],
                'level' => [
                    'type' => 'integer',
                ],
                'latitude' => [
                    'type' => 'float',
                ],
                'longitude' => [
                    'type' => 'float',
                ],
                'slug' => [
                    'type' => 'text',
                ],
                'uuid' => [
                    'type' => 'text',
                ],
                'lat_long' => [
                    'type' => 'geo_point',
                ],
            ]
        ];

        return \array_merge_recursive($defaultMappings, $mappings, $this->translationMapping());
    }
}
# vendor/phoenix/api-bundle/Resources/config/services_elasticsearch.yaml

Phoenix\ApiBundle\Elasticsearch\Index\LocationIndex:
    arguments: ['@Phoenix\ApiBundle\Elasticsearch\Document\LocationDocument']
    tags: ['es.index']
    calls:
        - [setPrefix, ['%pes.index_prefix%']]

Create document class and register it as service with 'es.document' tag:

// vendor/phoenix/api-bundle/Elasticsearch/Document/LocationDocument.php

<?php

/*
 * This file is part of the Phoenix package.
 *
 * (c) Hiren Chhatbar <hc.rajkot@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Phoenix\ApiBundle\Elasticsearch\Document;

use Phoenix\ElasticsearchBundle\Document\AbstractDocument;
use Doctrine\ORM\QueryBuilder;
use Phoenix\ApiBundle\Service\QueryService;
use App\Entity\Location;
use Phoenix\ApiBundle\EntityService\LocationService;

/**
 * Class LocationDocument
 *
 * @package Phoenix\ApiBundle\Document
 * @author Hiren Chhatbar
 */
class LocationDocument extends AbstractDocument
{
    /**
     * Holds object of QueryService.
     *
     * @var QueryService
     */
    protected QueryService $queryService;

    /**
     * Holds object of LocationService.
     *
     * @var LocationService
     */
    protected LocationService $locationService;

    /**
     * Constructor.
     *
     * @param QueryService $queryService
     * @param LocationService $locationService
     */
    public function __construct(QueryService $queryService, LocationService $locationService)
    {
        $this->queryService = $queryService;

        $this->locationService = $locationService;
    }

    /**
     * {@inheritDoc}
     *
     * @see \Phoenix\ElasticsearchBundle\Document\DocumentInterface::get()
     */
    public function get(int $id): array
    {
        $res = $this->queryService->select('location__find_one', ['id' => $id]);

        $row = \reset($res['rows']);

        if ($row['latitude'] && $row['longitude']) {
            $row['lat_long'] = sprintf('%s,%s', $row['latitude'], $row['longitude']);
        }

        $resTrans = $this->queryService->select('location_translation__find_by_object', ['object' => $id]);

        foreach ($resTrans['rows'] as $rowTrans) {
            unset($rowTrans['id']);

            $row['translation'][] = $rowTrans;

            $fullnameTrans = [
                'locale' => $rowTrans['locale'],
                'field' => 'fullname',
                'content' => $this->locationService->hierarchyAsString($row['id'], $rowTrans['locale']),
            ];

            $row['translation'][] = $fullnameTrans;
        }

        $row['parent'] = $row['parent_id'];

        unset($row['parent_id']);

        return $row;
    }

    /**
     * {@inheritDoc}
     *
     * @see \Phoenix\ElasticsearchBundle\Document\DocumentInterface::queryBuilder()
     */
    public function queryBuilder(): QueryBuilder
    {
        $qb = $this->queryService->repository(Location::class)->createQueryBuilder('l');

        $qb->select('l.id');

        return $qb;
    }
}
# vendor/phoenix/api-bundle/Resources/config/services_elasticsearch.yaml

Phoenix\ApiBundle\Elasticsearch\Document\LocationDocument:
    arguments: ['@Phoenix\ApiBundle\Service\QueryService', '@Phoenix\ApiBundle\EntityService\LocationService']
    tags: ['es.document']

Use DI (Dependancy Injection) and use Phoenix\ElasticsearchBundle\Service and its search method to execute search query:

// vendor/phoenix/api-bundle/CrudManipulator/LocationAdminCrudManipulator.php

<?php
/*
 * This file is part of the Phoenix package.
 *
 * (c) Hiren Chhatbar <hc.rajkot@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Phoenix\ApiBundle\CrudManipulator;

use Phoenix\ElasticsearchBundle\Service\DocumentService;
use Phoenix\ApiBundle\Elasticsearch\Index\LocationIndex;
use Phoenix\ElasticsearchBundle\Utils\Pagination;
use Phoenix\ElasticsearchBundle\Utils\Util;

/**
 * Class LocationCrudManipulator
 *
 * @package Phoenix\ApiBundle\CrudManipulator
 * @author Hiren Chhatbar
 */
class LocationAdminCrudManipulator extends AbstractCrudManipulator
{
    /**
     * Holds object of LocationIndex.
     *
     * @var LocationIndex
     */
    protected LocationIndex $locationIndex;

    /**
     * Holds object of DocumentService.
     *
     * @var DocumentService
     */
    protected DocumentService $documentService;

    /**
     * Holds object of Pagination.
     *
     * @var Pagination
     */
    protected Pagination $pagination;

    /**
     * Holds object of Util.
     *
     * @var Util
     */
    protected Util $util;

    /**
     * Constructor.
     *
     * @param LocationIndex $locationIndex
     * @param DocumentService $documentService
     * @param Pagination $pagination
     */
    public function __construct(LocationIndex $locationIndex, DocumentService $documentService, Pagination $pagination, Util $util)
    {
        $this->locationIndex = $locationIndex;

        $this->documentService = $documentService;

        $this->pagination = $pagination;

        $this->util = $util;
    }
    /**
     * Returns list.
     *
     * @param array $input
     *
     * @return array
     */
    public function list(array $input): array
    {
        $ret = [];

        $limit = $input['limit'] ?? 30;
        $offset = $input['offset'] ?? 0;

        $body = [];

        if (isset($input['name'])) {
            $body['query']['bool']['filter'][]['wildcard']['name'] = [
                'value' => \sprintf('*%s*', $this->util->escape($input['name'])),
            ];
        }

        if (isset($input['fullname'])) {
            $body['query']['bool']['filter'][]['wildcard']['fullname'] = [
                'value' => \sprintf('*%s*', \sprintf('*%s*', $this->util->escape($input['fullname']))),
            ];
        }

        if (isset($input['parent'])) {
            $location = $input['parent'];

            $body['query']['bool']['filter'][]['term']['parent'] = [
                'value' => $location->getId(),
            ];
        }

        if (isset($input['path'])) {
            $body['query']['bool']['filter'][]['wildcard']['path'] = [
                'value' => \sprintf('*%s*', \sprintf('%s*', $this->util->escape($input['path']))),
            ];
        }

        if (isset($input['order_by']) && $input['order_by']) {
            $fld = key($input['order_by']);

            $ord = $input['order_by'][$fld];

            $body['sort'][] = [$fld => $ord];
        }

        $res = $this->documentService->search(
            $this->index->name(),
            $body,
            $offset,
            $limit,
            true
        );

        $ret = \array_merge(
            $this->pagination->info($res['hits']['total']['value'], $limit, $offset),
            ['rows' => \array_column($res['hits']['hits'], '_source')]
        );

        return $ret;
    }
}

Commands

Server related commands

// Pings server
php bin/console phoenix:elasticsearch:client ping

// Displays server info
php bin/console phoenix:elasticsearch:client info

Index related commands

// Creates index for location
php bin/console phoenix:elasticsearch:index --name=location create
// Deletes index of location
php bin/console phoenix:elasticsearch:index --name=location delete
// Checks whether index for location exists or not
php bin/console phoenix:elasticsearch:index --name=location exists
// Displays settings of index for location
php bin/console phoenix:elasticsearch:index --name=location settings
// Displays mappings of index for location
php bin/console phoenix:elasticsearch:index --name=location mappings
// Updates settings in index for location
php bin/console phoenix:elasticsearch:index --name=location update-settings
// Updates settings in index for location
php bin/console phoenix:elasticsearch:index --name=location update-mappings

Document related commands

// Index single document of location of ID given
php bin/console phoenix:elasticsearch:document --index=location --id=10 sync-by-id
// Index all documents of location
php bin/console phoenix:elasticsearch:document --index=location sync
// Delete all documents of location
php bin/console phoenix:elasticsearch:document --index=location delete-all
// Delete single document of given ID of location
php bin/console phoenix:elasticsearch:document --index=location --id=10 delete-by-id
// Displays document of given ID of location
php bin/console phoenix:elasticsearch:document --index=location --id=10 get

Todo

  • Autocomplete

Roadmap

Core library

About

The bundle works like a bridge to integrate Elasticsearch in Symfony. It provides developer APIs and eco-system to work with Elasticsearch easily using dependency injection (DI).

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages