Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fields not indexed #378

Open
DestockMotor opened this issue Dec 2, 2023 · 0 comments
Open

Fields not indexed #378

DestockMotor opened this issue Dec 2, 2023 · 0 comments

Comments

@DestockMotor
Copy link

  • 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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant