Coder Social home page Coder Social logo

doctrine / search Goto Github PK

View Code? Open in Web Editor NEW
274.0 274.0 56.0 657 KB

Generic Search extension for indexing and querying ODM/ORM objects with different text-search engine implementations

Home Page: http://www.doctrine-project.org

License: MIT License

PHP 100.00%

search's Introduction

Doctrine Search

Note: This project is a prototype at the moment. See demo folder for practical implementation example.

Supported search engines

Features

  • SearchManager
    • Can be used stand-alone or in a hybrid configuration
    • Configurable search manager supports aggregate entity manager
    • supports direct API calls through search engine adapters such as Elastica
    • transforms returned ID's via batch operation into hydrated objects as required
    • Supports event manager listeners for customizable entity handling
  • Support for indexing through event listeners via JMS Serializer or simple entity callback.
  • Annotations for index and data type creation using ObjectManager::getClassMetadata() as the base structure

#Usage#

Configuration

The search manager connection can be configured as shown in the following example:

$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
);

Mappings

Basic entity mappings for index and type generation can be annotated as shown in the following example. Mappings can be rendered into a format suitable for automatically generating indexes and types using a build script (advanced setup required).

<?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);
  }
}

Indexing

Documents can be serialized for indexing currently in the following ways. If required an event listener can be used with your ORM as shown in this example. If an event listener is not needed, entities can be persisted or removed directly using the search manager.

<?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

This approach simply expects a toArray() method on the entity, although this method be configured as required. The interface suggested in this example can be any interface you desire, as long as your event listener can identify entities that need to be persisted to the search engine (see above example).

...
use Entities\Behaviour\SearchableEntityInterface

class Post implements SearchableEntityInterface
{
  ...
  public function toArray() {
    return array(
      'id' => $this->id,
      'title' => $this->title,
      'content' => $this->content
      ...
    );
  }
}

JMS Serializer

You can alternatively use the advanced serialization power of the JMS Serializer to automatically handle serialization for you based on annotations such as those shown in this example.

...
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

Not yet available.

Queries

Queries can be executed through the search manager as shown below. Use of the result cache refers to using the cache for the hydration query. Search engine specific adapter interfaces are exposed magically so as in this example, Elastica\Query::addSort method is amalgamated with Doctrine\Search\Query methods. Thus any complexity of query supported by the search engine client library is supported.

$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();

Simple Repository ID queries and Term search can by done using the following technique. Deserialization is done independently of Doctrine\ORM but the same models are hydrated according to the registered SerializerInterface.

$entity = $searchManager->getRepository('Entities\Post')->find($id);
$entity = $searchManager->getRepository('Entities\Post')->findOneBy(array($key => $term));

search's People

Contributors

akleiber avatar baachi avatar beberlei avatar fprochazka avatar lsmith77 avatar mikelohmann avatar mrhash avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

search's Issues

Can anyone provide a working example?

Hi, I am wondering if anyone can provide a working example with doctrine/search, maybe someone of the guys who forked this repo as it seems that it is not maintained anymore?!
Unfortunately the documentation in the readme does not work. Thanks a lot :-)

Implement ClassMetaData

The ClassMetadata should be used to hold all meta-data of a document regarding search parameters.

Fix errors in phpdocs

Many files have a phpdoc error.

  • missing method/class docblock
  • wrong indentation
  • missing licence block
  • ...

Event subscriber can't get entities

If you write an event subscriber for the preFlush event, you only get the SearchManager as argument. Unfortunately the search manager isn't capable of returning the entities which will get flushed. I need them to interact with them before flushing them. Can this be implemented somehow or isn't it supposed to be that way? How do you get your entities in an event subscriber in general?

Edit: Just looked up the source of doctrine. You can get the unit of work by the search manager. And the doctrine unit of work has a function for returning entities, but not the doctrine/search unit of work: http://www.doctrine-project.org/api/orm/2.4/source-class-Doctrine.ORM.UnitOfWork.html#_getIdentityMap
Would it be possible to implement that or can I do a pull request?

Request constants

I think it was useful to create constants for the request methods.

const METHOD_HEAD = 'head';
const METHOD_GET    = 'get';
const METHOD_POST = 'post';

Error in Buzz/lib/Buzz/Client/FileGetContents.php causes Doctrine/Search/Http/Client/BuzzTest.php to fail

There seems to be an error within the /Buzz/lib/Buzz/Client/FileGetContents.php when executing the Doctrine/Search/Http/Client/BuzzTest.php. Therefor I just commented out the BuzzTest::testCallNotExistingHost-Test to commit my changes.

  1. Doctrine\Search\Http\Adapter\Client\BuzzTest::testCallNotExistingHost
    Undefined variable: http_response_header

/Users/mikelohmann/Sites/doctrine-search.local/search/lib/vendor/Buzz/lib/Buzz/Client/FileGetContents.php:49
/Users/mikelohmann/Sites/doctrine-search.local/search/lib/vendor/Buzz/lib/Buzz/Browser.php:87
/Users/mikelohmann/Sites/doctrine-search.local/search/lib/vendor/Buzz/lib/Buzz/Browser.php:66
/Users/mikelohmann/Sites/doctrine-search.local/search/lib/Doctrine/Search/Http/Client/BuzzClient.php:53
/Users/mikelohmann/Sites/doctrine-search.local/search/tests/Doctrine/Search/Http/Client/BuzzTest.php:41

explore the viability of a simple http client in doctrine common

just wanted to open this as a ticket. i think it totally makes sense to use Buzz right now. but once all the core pieces are in place, we should review once more if we cannot simple move the CouchDB ODM HTTP client to common along with an interface and potentially a few adaptors for popular http clients.

Specifying the index

I know this is an old project and a prototype but I have been using it for my application with ElasticSearch and it is working very well. I am very pleased with it.

I would like to make is to that the Index can be specified by other means rather than in Annotations on the model. I have looked at the code and seen that this creation is quite a long way along the code path. Do you have any suggestions on the easiest way to pass in the index name as a variable rather than in the annotation?

I hope that makes sense.

Thanks, Russell

RoutingMissingException[routing is required for [search]/[images]/[86]]

Hello,

I am using this library for persisting Doctrine entities in Elasticsearch using Doctrine life cycle events. I have two types: images and photographers. Photographers are set as parent of images. Here are their mappings:

{
    "my_search" : {
        "mappings" : {
            "photographers" : {
                "properties" : {
                    "fullName" : {
                        "type" : "string",
                        "include_in_all" : true
                    }
                }
            },
            "images" : {
                "_parent" : {
                    "type" : "photographers"
                },
                "_routing" : {
                    "required" : true
                },
                "properties" : {
                    "description" : {
                        "type" : "string",
                        "include_in_all" : true
                    },
                    "headline" : {
                        "type" : "string",
                        "include_in_all" : true
                    }
                }
            }
        }
    }
}

On image postPersist/postUpdate this exception is thrown:

Elastica\Exception\ResponseException
File:
    /var/www/search/vendor/ruflin/elastica/lib/Elastica/Transport/Http.php:146
Message:
    RoutingMissingException[routing is required for [my_search]/[images]/[86]]

I use the same annotations like the entities in the demo folder of the library. The demo works fine, but my code doesn't.

Can someone give me a hint what could be the problem? Any help will be appreciated!
Thanks in advance.

Why Buzz?

Can you tell me, why you will using the Buzz library?

Support for ManyToMany, ManyToOne, OneToMany

It is possible to support classic relational ManyToMany, ManyToOne, OneToMany by adding event subscribers which handle this before flushing entities. How about taking this into the lib by extending with doctrine annotations and instead of event subscribers, check for these relations right before flushing.

Advantage: You do not have to write your own subscriber. Although there are possibilities like nested documents etc. there are some cases where you definitely need classical relational relationships and you need some mechanism to update everything automatically instead of doing it all yourself. Like the usual doctrine behaviour.

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.