Git Product home page Git Product logo

solrbundle's Introduction

SolrBundle

Introduction

Forked from floriansemm/solr-bundle to integrate with Solarium 5, Symfony > 4.3

This Bundle provides a simple API to index and query a Solr Index.

Installation

  1. Download SolrBundle
  2. Enable the Bundle
  3. Configure the SolrBundle
  4. configure your entity

Step 1: Download SolrBundle

This bundle is available on Packagist. You can install it using Composer:

$ composer require maxgr0/solr-bundle

Step 2: Enable the bundle

When using Symfony Flex, you can skip this step.

Next, enable the bundle in the kernel:

<?php
// app/AppKernel.php

public function registerBundles()
{
    $bundles = array(
        // ...
        new FS\SolrBundle\FSSolrBundle(),
    );
}

Step 3: Configure the SolrBundle

Finally, configure the bundle:

# app/config/fs_solr.yml
fs_solr:
    endpoints:
        core0:
            schema: http
            host: host
            port: 8983
            path: /
            core: corename
            timeout: 5

Default values will be used for any option left out.

With DSN

# app/config/fs_solr.yml
fs_solr:
    endpoints:
        core0:
            dsn: http://host:8983/
            core: core0
            timeout: 5

Any values in schema, host, port and path option, will be ignored if you use the dsn option.

Step 4: Configure your entities

To make an entity indexed, you must add some annotations to your entity. Basic configuration requires two annotations: @Solr\Document(), @Solr\Id(). To index data add @Solr\Field() to your properties.

If you want to index documents without any database, then you have to use the same annotations. Make sure you have set a Id or set @Solr\Id(generateId=true).

// ....
use FS\SolrBundle\Doctrine\Annotation as Solr;
    
/**
* @Solr\Document()
* @ORM\Table()
*/
class Post
{
    /**
     * @Solr\Id
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;
    
    /**
     * @Solr\Field(type="string")
     *
     * @ORM\Column(name="title", type="string", length=255)
     */
    private $title = '';

    /**
     * @Solr\Field(type="string")
     *
     * @ORM\Column(name="text", type="text")
     */
    private $text = '';

   /**
    * @Solr\Field(type="date", getter="format('Y-m-d\TH:i:s.z\Z')")
    *
    * @ORM\Column(name="created_at", type="datetime")
    */
    private $created_at = null;
}

The bundle handles now updates / inserts / deletions for your configured entity.

Annotation reference

@Solr\Document annotation

This annotation denotes that an entity should be indexed as a document. It has several optional properties:

  • repository
  • index
  • indexHandler

Setting custom repository class with repository option

If you specify your own repository, the repository must extend the FS\SolrBundle\Repository\Repository class.

/**
 * @Solr\Document(repository="My/Custom/Repository")
 */
class SomeEntity
{
    // ...
}

index property

It is possible to specify a core the document will be indexed in:

/**
 * @Solr\Document(index="core0")
 */
class SomeEntity
{
    // ...
}

indexHandler property

By default, all documents will be indexed in the core core0. If your entities/documents have different languages, then you can setup a callback method, which should return the core the entity will be indexed in.

/**
 * @Solr\Document(indexHandler="indexHandler")
 */
class SomeEntity
{
    public function indexHandler()
    {
        if ($this->language == 'en') {
            return 'core0';
        }
    }
}

Each core must be set up in config.yml under endpoints. If you leave the index or indexHandler property empty, then the default core will be used (first one in the endpoints list). To index a document in all cores, use * as index value.

@Solr\Id annotation

This annotation is required to index an entity. The annotation has no properties. You should add this annotation to the field that will be used as the primary identifier for the entity/document.

class Post
{
    /**
     * @Solr\Id
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */

    private $id;
}

generateId option

Set this option to true and a the bundle will generate a Id for you. Use this option if you have no underlying DB which generates incremental Ids for you.

@Solr\Field annotation

This annotation should be added to properties that should be indexed. You should specify the type option for the annotation.

type property

Currently, a basic set of types is implemented:

  • string(s)
  • text(s)
  • date(s)
  • integer(s)
  • float(s)
  • double(s)
  • long(s)
  • boolean(s)

If you have a customized schema.xml than you don't need to setup a field-type.

fieldModifier property

Solr supports partial updates of fields in an existing document. Supported values are:

  • set
  • add (multivalue field only, adds a value(s) to a existing list)
  • remove (multivalue field only, removes a value(s) from existing list)
  • inc (integer field only)

nestedClass property

Set this property if you want to index collections with nested Objects.

Object relations

For more information read the more detailed "How to index relation" guide

@Solr\SynchronizationFilter(callback="shouldBeIndexed") annotation

In some cases, an entity should not be indexed. For this, you have the SynchronizationFilter annotation to run a filter-callback.

/**
 * // ....
 * @Solr\SynchronizationFilter(callback="shouldBeIndexed")
 */
class SomeEntity
{
    /**
     * @return boolean
    */
    public function shouldBeIndexed()
    {
        // put your logic here
    }
}

The callback property specifies an callable function, which should return a boolean value, specifying whether a concrete entity should be indexed.

Queries

Query a field of a document

Querying the index is done via the solr.client service:

$query = $this->get('solr.client')->createQuery('AcmeDemoBundle:Post');
$query->addSearchTerm('title', 'my title');
$query->addSearchTerm('collection_field', array('value1', 'value2'));

$result = $query->getResult();

or

$posts = $this->get('solr.client')->getRepository('AcmeDemoBundle:Post')->findOneBy(array(
    'title' => 'my title',
    'collection_field' => array('value1', 'value2')
));

Query all fields of a document

The previous examples were only querying the title field. You can also query all fields with a string.

$query = $this->get('solr.client')->createQuery('AcmeDemoBundle:Post');
$query->queryAllFields('my title');

$result = $query->getResult();

Define a custom query string

If you need more flexiblity in your queries you can define your own query strings:

$query = $this->get('solr.client')->createQuery('AcmeDemoBundle:Post');
$query->setCustomQuery('id:post_* AND (author_s:Name1 OR author_s:Name2)');

$result = $query->getResult();

The QueryBuilder

The query-builder based on https://github.com/minimalcode-org/search Criteria API.

$queryBuilder = $this->get('solr.client')->getQueryBuilder('AcmeDemoBundle:Post');
$result = $queryBuilder
    ->where('author')
        ->is('Name1')
    ->orWhere('author')
        ->is('Name2')
    ->getQuery()
    ->getResult();

To keep your code clean you should move the select-criteria in a repository-class:

class YourRepository extends Repository
{
    public function findAuthor($name1, $name2)
    {
        return $this->getQueryBuilder()
            ->where('author')
                ->is($name1)
            ->orWhere('author')
                ->is($name2)
            ->getQuery()
            ->getResult();
    }
}

Configure HydrationModes

HydrationMode tells the bundle how to create an entity from a document.

  1. FS\SolrBundle\Doctrine\Hydration\HydrationModes::HYDRATE_INDEX - use only the data from solr
  2. FS\SolrBundle\Doctrine\Hydration\HydrationModes::HYDRATE_DOCTRINE - merge the data from solr with the entire doctrine-entity

With a custom query:

$query = $this->get('solr.client')->createQuery('AcmeDemoBundle:Post');
$query->setHydrationMode($mode)

With a custom document-repository you have to set the property $hydrationMode itself:

public function find($id)
{
    $this->hydrationMode = HydrationModes::HYDRATE_INDEX;
    
    return parent::find($id);
}

Repositories

Your should define your own repository-class to make your custom queries reuseable. How to configure a repository for a document have a look at the annotation section

namespace AppBundle\Search;

use FS\SolrBundle\Repository\Repository;

class ProviderRepository extends Repository
{
    public function findPost($what)
    {
        $query = $this->solr->createQuery('AcmeDemoBundle:Post');
        // some query-magic here

        return $query->getResult();
    }
}

In your repository you have full access to the querybuilder.

Commands

Here's all the commands provided by this bundle:

  • solr:index:clear - delete all documents in the index
  • solr:index:populate - synchronize the db with the index
  • solr:schema:show - shows your configured documents

Indexing huge sets of entities

The solr:index:populate command works well for sets up to 300k entities, everthing large makes the command very slow. You can find here some solution how to sync your DB with Solr.

Extend Solarium

To extend Solarium with your own plugins, create a tagged service:

<tag name="solarium.client.plugin" plugin-name="yourPluginName"/>

To hook into the Solarium events create a common Symfony event-listener:

<tag name="kernel.event_listener" event="solarium.core.preExecuteRequest" method="preExecuteRequest" />

Document helper

Retrieve the last insert entity-id

$helper = $this->get('solr.client')->getDocumentHelper();
$id = $helper->getLastInsertDocumentId();

solrbundle's People

Contributors

floriansemm avatar royopa avatar zquintana avatar bb-fuf avatar burki avatar maxgr0 avatar frne avatar boppy avatar jkwakman avatar marfillaster avatar patrikorup avatar dcaillibaud avatar alcaeus avatar gigo6000 avatar chellem avatar jakesylvestre avatar josephwoodward avatar intel352 avatar arcanis avatar nathankot avatar kix avatar gitter-badger avatar

Watchers

James Cloos avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.