Search code examples
phpsymfonyelasticsearchdoctrine-ormongr

ongr-io elasticsearch bundle implementation with doctrine symfony2


In our symfony2 project we want to implement elasticsearch with ongr-io bundle, but our whole system is built on doctrine. Is it possible to somehow use ongr-io elasticsearch bundle without totally redoing whole database with documents instead of entities?

Entity that I want to index (fields for search would be: name, ChildCategory and ParentCategory):

/**
 * Course
 *
 * @ORM\Table(name="course")
 * @ORM\Entity(repositoryClass="CoreBundle\Repository\CourseRepository")
 * @ORM\HasLifecycleCallbacks
 */
    class Course
    {
        /**
         * @var int
         *
         * @ORM\Column(name="id", type="integer")
         * @ORM\Id
         * @ORM\GeneratedValue(strategy="AUTO")
         */
        private $id;

        /**
         * @var string
         *
         * @ORM\Column(name="name", type="string", length=255, unique=false)
         */
        private $name;

        /**
         * @var ParentCategory
         *
         * @ORM\ManyToOne(targetEntity="ParentCategory")
         * @ORM\JoinColumn(name="parentCategory_id", referencedColumnName="id")
         */
        private $parentCategory;

        /**
         * @var ChildCategory
         *
         * @ORM\ManyToOne(targetEntity="ChildCategory", inversedBy="courses")
         * @ORM\JoinColumn(name="childCategory_id", referencedColumnName="id")
         */
        private $childCategory;

        /**
         * @var City
         *
         * @ORM\ManyToOne(targetEntity="City")
         * @ORM\JoinColumn(name="city_id", referencedColumnName="id")
         */
        private $city;

        /**
         * @var Users
         *
         * @ORM\ManyToOne(targetEntity="UserBundle\Entity\Users", inversedBy="course")
         * @ORM\JoinColumn(name="owner_id", referencedColumnName="id")
         */
        private $owner;

        /**
         * @var text
         *
         * @ORM\Column(name="description", type="text")
         */
        private $description;

        /**
         * @var Picture
         *
         * @ORM\OneToMany(targetEntity="CoreBundle\Entity\Picture", mappedBy="course", cascade={"persist", "remove"})
         */
        private $pictures;

        /**
         * @var Ratings
         *
         * @ORM\OneToMany(targetEntity="CoreBundle\Entity\Ratings", mappedBy="courseid")
         */
        private $ratings;

        public $avgRating;
    }

Solution

  • it's very interesting.

    The first thing is Entity location. The document for ElasticsearchBundle has to be in Document directory. It's not a big deal. All you need to do is to create an empty class and extend entity with @Document annotation. Next are the fields. With name field there is no problem at all, just add @property annotation and you are good. More interesting is with relations. My suggestion would be to create separate property and in the getter return value from the relation for that field. I hope you got the idea.

    Update:

    Here's an example of documents:

    AppBundle/Entity/Post

    <?php
    
    namespace AppBundle\Entity;
    
    use Doctrine\ORM\Mapping as ORM;
    use ONGR\ElasticsearchBundle\Annotation as ES;
    
    /**
     * Post
     *
     * @ORM\Table(name="post")
     * @ORM\Entity(repositoryClass="AppBundle\Repository\PostRepository")
     */
    class Post
    {
        /**
         * @var int
         *
         * @ORM\Column(name="id", type="integer")
         * @ORM\Id
         * @ORM\GeneratedValue(strategy="AUTO")
         */
        private $id;
    
        /**
         * @var string
         *
         * @ES\Property(type="string")
         * @ORM\Column(name="title", type="string", length=255, nullable=true)
         */
        private $title;
    
        /**
         * @var User
         *
         * @ORM\ManyToOne(targetEntity="User")
         * @ORM\JoinColumn(name="user_id", referencedColumnName="id")
         */
        private $user;
    
        /**
         * @var string
         *
         * @ES\Property(name="user", type="string")
         */
        private $esUser;
    
        /**
         * Get id
         *
         * @return int
         */
        public function getId()
        {
            return $this->id;
        }
    
        /**
         * Set title
         *
         * @param string $title
         *
         * @return Post
         */
        public function setTitle($title)
        {
            $this->title = $title;
    
            return $this;
        }
    
        /**
         * Get title
         *
         * @return string
         */
        public function getTitle()
        {
            return $this->title;
        }
    
        /**
         * Set user
         *
         * @param \AppBundle\Entity\User $user
         *
         * @return Post
         */
        public function setUser(\AppBundle\Entity\User $user = null)
        {
            $this->user = $user;
    
            return $this;
        }
    
        /**
         * Get user
         *
         * @return \AppBundle\Entity\User
         */
        public function getUser()
        {
            return $this->user;
        }
    
        /**
         * @return string
         */
        public function getEsUser()
        {
            return $this->esUser;
        }
    
        /**
         * @param string $esUser
         */
        public function setEsUser($esUser)
        {
            $this->esUser = $esUser;
        }
    }
    

    AppBundle/Document/Post

    <?php
    
    namespace AppBundle\Document;
    
    use ONGR\ElasticsearchBundle\Annotation as ES;
    use AppBundle\Entity\Post as OldPost;
    
    /**
     * @ES\Document()
     */
    class Post extends OldPost
    {
    }