algolia / search-bundle

Seamless integration of Algolia Search into your Symfony project.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Fields not indexed

DestockMotor opened this issue · comments

  • Symfony version: 5.4.25
  • Algolia Search Bundle version: 6.0.1

Description

I have a simple entity with a custom type field, a Point for storing a location. The field is "tagged" as searchable but appears empty in my indexes.

The entity:

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping\Column;
use Doctrine\ORM\Mapping\CustomIdGenerator;
use Doctrine\ORM\Mapping\Entity;
use Doctrine\ORM\Mapping\GeneratedValue;
use Doctrine\ORM\Mapping\Id;
use Doctrine\ORM\Mapping\ManyToOne;
use Doctrine\ORM\Mapping\Table;
use Gedmo\Mapping\Annotation\Timestampable;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints\NotBlank;

#[Entity]
#[Table(name: 'event')]
class Event
{
    #[Id]
    #[GeneratedValue(strategy: 'CUSTOM')]
    #[CustomIdGenerator(class: UUIDGenerator::class)]
    #[Column]
    #[Groups(['apiExposed', 'searchable'])]
    private string $id;

    #[Column]
    #[Groups(['apiExposed', 'searchable'])]
    #[NotBlank]
    private string $title;

    #[Column(type: 'point')]
    #[Groups(['apiExposed', 'searchable'])]
    #[NotBlank]
    private Point $location;

    #[ManyToOne(targetEntity: User::class)]
    #[Groups('apiExposed')]
    #[NotBlank]
    private User $organizer;

    #[Column]
    #[Groups(['apiExposed', 'searchable'])]
    #[NotBlank]
    private string $description;

    #[Column]
    #[Groups(['apiExposed', 'searchable'])]
    private bool $isSecret = false;

    #[Column]
    #[Groups(['apiExposed', 'searchable'])]
    private \DateTimeImmutable $startDate;

    #[Column]
    #[Groups('apiExposed')]
    #[Timestampable(on: 'create')]
    private \DateTimeImmutable $createdAt;

    #[Column]
    #[Groups('apiExposed')]
    #[Timestampable(on: 'update')]
    private \DateTimeImmutable $updatedAt;

    /**
     * @return string
     */
    public function getId(): string
    {
        return $this->id;
    }

    /**
     * @param string $id
     * @return Event
     */
    public function setId(string $id): Event
    {
        $this->id = $id;
        return $this;
    }

    /**
     * @return string
     */
    public function getTitle(): string
    {
        return $this->title;
    }

    /**
     * @param string $title
     * @return Event
     */
    public function setTitle(string $title): Event
    {
        $this->title = $title;
        return $this;
    }

    /**
     * @return Point
     */
    public function getLocation(): Point
    {
        return $this->location;
    }

    /**
     * @param Point $location
     * @return Event
     */
    public function setLocation(Point $location): Event
    {
        $this->location = $location;
        return $this;
    }

    /**
     * @return User
     */
    public function getOrganizer(): User
    {
        return $this->organizer;
    }

    /**
     * @param User $organizer
     * @return Event
     */
    public function setOrganizer(User $organizer): Event
    {
        $this->organizer = $organizer;
        return $this;
    }

    /**
     * @return string
     */
    public function getDescription(): string
    {
        return $this->description;
    }

    /**
     * @param string $description
     * @return Event
     */
    public function setDescription(string $description): Event
    {
        $this->description = $description;
        return $this;
    }

    /**
     * @return bool
     */
    public function isSecret(): bool
    {
        return $this->isSecret;
    }

    /**
     * @param bool $isSecret
     * @return Event
     */
    public function setIsSecret(bool $isSecret): Event
    {
        $this->isSecret = $isSecret;
        return $this;
    }

    /**
     * @return \DateTimeImmutable
     */
    public function getStartDate(): \DateTimeImmutable
    {
        return $this->startDate;
    }

    /**
     * @param \DateTimeImmutable $startDate
     * @return Event
     */
    public function setStartDate(\DateTimeImmutable $startDate): Event
    {
        $this->startDate = $startDate;
        return $this;
    }

    /**
     * @return \DateTimeImmutable
     */
    public function getCreatedAt(): \DateTimeImmutable
    {
        return $this->createdAt;
    }

    /**
     * @param \DateTimeImmutable $createdAt
     * @return Event
     */
    public function setCreatedAt(\DateTimeImmutable $createdAt): Event
    {
        $this->createdAt = $createdAt;
        return $this;
    }

    /**
     * @return \DateTimeImmutable
     */
    public function getUpdatedAt(): \DateTimeImmutable
    {
        return $this->updatedAt;
    }

    /**
     * @param \DateTimeImmutable $updatedAt
     * @return Event
     */
    public function setUpdatedAt(\DateTimeImmutable $updatedAt): Event
    {
        $this->updatedAt = $updatedAt;
        return $this;
    }
}

The Point entity:

<?php

namespace App\Entity;

use Symfony\Component\Serializer\Annotation\Groups;

class Point
{
    #[Groups('apiExposed', 'searchable')]
    private float $lat;

    #[Groups('apiExposed', 'searchable')]
    private float $long;

    public function __construct(float $lat, float $long)
    {
        $this -> lat = $lat;
        $this -> long = $long;
    }

    /**
     * @return float
     */
    public function getLat(): float
    {
        return $this->lat;
    }

    /**
     * @param float $lat
     * @return Point
     */
    public function setLat(float $lat): Point
    {
        $this->lat = $lat;
        return $this;
    }

    /**
     * @return float
     */
    public function getLong(): float
    {
        return $this->long;
    }

    /**
     * @param float $long
     * @return Point
     */
    public function setLong(float $long): Point
    {
        $this->long = $long;
        return $this;
    }

    public function __toString(): string
    {
        return sprintf('POINT(%f %f)', $this -> lat, $this -> long);
    }
}

And the Point type:

<?php

namespace App\Type;

use App\Entity\Point;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Types\Type;

class PointType extends Type
{
    const POINT = 'point';

    public function getSQLDeclaration(array $column, AbstractPlatform $platform)
    {
        return 'POINT';
    }

    public function getName()
    {
        return self::POINT;
    }

    public function convertToPHPValue($value, AbstractPlatform $platform)
    {
        list($lat, $long) = sscanf($value, 'POINT(%f %f)');
        return new Point($lat, $long);
    }

    public function convertToPHPValueSQL($sqlExpr, $platform)
    {
        return sprintf('AsText(%s)', $sqlExpr);
    }

    public function convertToDatabaseValue($value, AbstractPlatform $platform)
    {
        if ($value instanceof Point) {
            $value = sprintf('POINT(%F %F)', $value -> getLat(), $value -> getLong());
        }
        return $value;
    }

    public function convertToDatabaseValueSQL($sqlExpr, AbstractPlatform $platform)
    {
        return sprintf('PointFromText(%s)', $sqlExpr);
    }

    public function canRequireSQLConversion()
    {
        return true;
    }
}

Here is my SearchBundle config:

algolia_search:
    prefix: '%env(APP_ENV)%_'
    indices:
        - name: events
          class: App\Entity\Event
          enable_serializer_groups: true

The fact is I want the Points in Events to be indexed to make geo queries on it.

Steps To Reproduce