Запрос по ссылке в Doctrine ODM (Монго) - PullRequest
0 голосов
/ 19 ноября 2018

История

Воссоздание структуры монго для борьбы с проблемами памяти в прежнем подходе, когда продукт хранится в каждой локали, а все значения являются хешем массива (для обновления потребовалось много времени).

Текущая проблема

Я не могу выбрать продукты, содержащие указанный атрибут с ключом "x" и значением "y".

Aggregation \ Builder

Этот подход даст мне только локализованные значения (продукт может содержать 5000 значений для 30 локалей), он работает и работает быстрее, чем метод repositoryMethod для getValues ​​() в документе Value.

/**
 * @param Builder $builder
 * @param ExportFilters $exportFilters
 */
private function applyLocaleFilter(Builder &$builder, ExportFilters $exportFilters)
{
    if (!$exportFilters->hasLocales()) {
        return;
    }

    // reflectionClass lists properties (still want the name,created,etc with the results).
    $fields = MongoProduct::getFieldNames();

    // remove "values" key or else i get 5000 results instead of my filtered 90 results
    $fields = array_diff($fields, ['values']); 

    $exp = $builder->expr()->eq('$$value.locale', $exportFilters->getLocale());

    $builder
        ->project()
        ->includeFields($fields)
        ->field('values')
        ->filter('$values', 'value', $exp);
}

Я хотел использовать тот же подход, чтобы продолжать фильтровать значения, проверяя их значение и атрибут, на который ссылаются, например;

Я хочу, чтобы все продукты (со значениями для локали: "en_GB") соответствовали приведенному ниже утверждению

ссылка на атрибут для значения должна быть (screen_size) и должна иметь значение "16 дюймов"

вернет все продукты, которые соответствуют фильтрации атрибутов с локализованными значениями

Атрибут Монго

<?php

namespace \MongoBundle\Document;

use Doctrine\ODM\MongoDB\Mapping\Annotations\Index;
use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB;

    /**
     * Class MongoAttribute
     * @package \MongoBundle\Document
     *
     * @MongoDB\Document(
     *     repositoryClass="\MongoBundle\Document\Repository\MongoAttributeRepository",
     *     indexes={@Index(keys={"code"="desc", "name"="desc"}, options={"unique"=true})}
     * )
     */
    class MongoAttribute
    {
        /**
         * @var int
         * @MongoDB\Id(strategy="NONE")
         */
        private $id;

        /**
         * @var string
         * @MongoDB\Field(type="string")
         */
        private $code;

        /**
         * @var string
         * @MongoDB\Field(type="string")
         */
        private $name;

        /**
         * @var string
         * @MongoDB\Field(type="string")
         */
        private $type;

        /**
         * @var string
         * @MongoDB\Field(type="string")
         */
        private $pre_fix;

        /**
         * @var string
         * @MongoDB\Field(type="string")
         */
        private $post_fix;

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

    /**
     * @param int $id
     * @return $this
     */
    public function setId($id)
    {
        $this->id = $id;

        return $this;
    }

    /**
     * @return string
     */
    public function getCode()
    {
        return $this->code;
    }

    /**
     * @param string $code
     * @return $this
     */
    public function setCode($code)
    {
        $this->code = $code;

        return $this;
    }

    /**
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * @param string $name
     * @return $this
     */
    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }

    /**
     * @return string
     */
    public function getType()
    {
        return $this->type;
    }

    /**
     * @param string $type
     * @return $this
     */
    public function setType($type)
    {
        $this->type = $type;

        return $this;
    }

    /**
     * @param string $preFix
     * @return $this
     */
    public function setPreFix($preFix)
    {
        $this->pre_fix = $preFix;

        return $this;
    }

    /**
     * @return string
     */
    public function getPostFix()
    {
        return $this->post_fix;
    }

    /**
     * @param string $postFix
     * @return $this
     */
    public function setPostFix($postFix)
    {
        $this->post_fix = $postFix;

        return $this;
    }
}

Значение монго

<?php

namespace \MongoBundle\Document;

use Doctrine\ODM\MongoDB\Mapping\Annotations\Index;
use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB;

/**
 * Class MongoValue
 * @package \MongoBundle\Document
 *
 * @MongoDB\Document(repositoryClass="\MongoBundle\Document\Repository\MongoValueRepository",
 *     indexes={@Index(keys={"locale"="desc", "attribute"="desc", "id"="desc"}, options={"unique"=true})}
 * )
 */
class MongoValue
{
    /**
     * @var int
     * @MongoDB\Id(strategy="NONE")
     */
    private $id;

    /**
     * @var string
     * @MongoDB\Field(type="string")
     */
    private $locale;

    /**
     * @var string
     * @MongoDB\Field(type="string")
     */
    private $value;

    /**
     * @var MongoAttribute
     * @MongoDB\ReferenceOne(targetDocument="MongoAttribute", cascade={"persist"})
     */
    private $attribute;

    /**
     * @var MongoProduct
     * @MongoDB\ReferenceOne(targetDocument="MongoProduct", cascade={"persist"})
     */
    private $product;

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

    /**
     * @param int $id
     * @return $this
     */
    public function setId($id)
    {
        $this->id = $id;

        return $this;
    }

    /**
     * @return MongoAttribute
     */
    public function getAttribute()
    {
        return $this->attribute;
    }

    /**
     * @param MongoAttribute $attribute
     * @return $this
     */
    public function setAttribute(MongoAttribute $attribute)
    {
        $this->attribute = $attribute;

        return $this;
    }

    /**
     * @return string
     */
    public function getLocale()
    {
        return $this->locale;
    }

    /**
     * @param string $locale
     * @return $this
     */
    public function setLocale($locale)
    {
        $this->locale = $locale;

        return $this;
    }

    /**
     * @return string
     */
    public function getValue()
    {
        return $this->value;
    }

    /**
     * @param string $value
     * @return $this
     */
    public function setValue($value)
    {
        $this->value = $value;

        return $this;
    }

    /**
     * @return MongoProduct
     */
    public function getProduct()
    {
        return $this->product;
    }

    /**
     * @param MongoProduct $product
     * @return $this
     */
    public function setProduct(MongoProduct $product)
    {
        $this->product = $product;

        return $this;
    }
}

Монго Продукт

<?php

namespace \MongoBundle\Document;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB;
use Doctrine\ODM\MongoDB\Mapping\Annotations\Index;
use ReflectionClass;
use \CatalogBundle\Entity\Locale;

/**
 * Class MongoProduct
 * @package \MongoBundle\Document
 *
 * @MongoDB\Document(repositoryClass="\MongoBundle\Document\Repository\MongoProductRepository",
 *     indexes={@Index(keys={"id"="desc", "name"="desc"}, options={"unique"=true})}
 * )
 */
class MongoProduct
{
    /**
     * @var integer
     * @MongoDB\Id(strategy="NONE")
     */
    protected $id;

    /**
     * @var string
     * @MongoDB\Field(type="string")
     */
    protected $name;

    /**
     * @var \DateTime
     * @MongoDB\Field(type="date")
     */
    protected $created;

    /**
     * @var \DateTime
     * @MongoDB\Field(type="date")
     */
    protected $updated;

    /**
     * @var boolean
     * @MongoDB\Field(type="bool")
     */
    protected $archived;

    /**
     * @var integer
     * @MongoDB\Field(type="bool")
     */
    protected $is_parent;

    /**
     * @var integer
     * @MongoDB\Field(type="bool")
     */
    protected $is_child;

    /**
     * @var boolean
     * @MongoDB\Field(type="bool")
     */
    protected $is_single;

    /**
     * @var string
     * @MongoDB\Field(type="string")
     */
    protected $attribute_set_id;

    /**
     * @var string
     * @MongoDB\Field(type="string")
     */
    protected $attribute_set_name;

    /**
     * @var MongoProduct
     * @MongoDB\ReferenceOne(targetDocument="MongoProduct")
     */
    protected $parent;

    /**
     * @var MongoProduct[]
     * @MongoDB\ReferenceMany(targetDocument="MongoProduct", cascade={"persist"}, orphanRemoval=true)
     */
    protected $children;

    /**
     * @var MongoValue[]
     * @MongoDB\ReferenceMany(targetDocument="MongoValue", cascade={"persist"}, orphanRemoval=true)
     */
    protected $values;

    /**
     * MongoProduct constructor.
     */
    public function __construct()
    {
        $this->children = new ArrayCollection();
        $this->values = new ArrayCollection();
    }

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

    /**
     * @param int $id
     * @return $this
     */
    public function setId($id)
    {
        $this->id = $id;

        return $this;
    }

    /**
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * @param string $name
     * @return $this
     */
    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }

    /**
     * @return \DateTime
     */
    public function getCreated()
    {
        return $this->created;
    }

    /**
     * @return \DateTime
     */
    public function getUpdated()
    {
        return $this->updated;
    }

    /**
     * @param \DateTime $updated
     * @return $this
     */
    public function setUpdated(\DateTime $updated)
    {
        $this->updated = $updated;

        return $this;
    }

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

    /**
     * @param bool $archived
     * @return $this
     */
    public function setArchived($archived)
    {
        $this->archived = $archived;

        return $this;
    }

    /**
     * @return int
     */
    public function getIsParent()
    {
        return $this->isParent;
    }

    /**
     * @param int $isParent
     * @return $this
     */
    public function setIsParent($isParent)
    {
        $this->isParent = $isParent;

        return $this;
    }

    /**
     * @return int
     */
    public function getIsChild()
    {
        return $this->is_child;
    }

    /**
     * @param int $isChild
     * @return $this
     */
    public function setIsChild($isChild)
    {
        $this->is_child = $isChild;

        return $this;
    }

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

    /**
     * @param bool $isSingle
     * @return $this
     */
    public function setIsSingle($isSingle)
    {
        $this->is_single = $isSingle;

        return $this;
    }

    /**
     * @return string
     */
    public function getAttributeSetId()
    {
        return $this->attribute_set_id;
    }

    /**
     * @param string $attributeSetId
     * @return $this
     */
    public function setAttributeSetId($attributeSetId)
    {
        $this->attribute_set_id = $attributeSetId;

        return $this;
    }

    /**
     * @return string
     */
    public function getAttributeSetName()
    {
        return $this->attribute_set_name;
    }

    /**
     * @param string $attributeSetName
     * @return $this
     */
    public function setAttributeSetName($attributeSetName)
    {
        $this->attribute_set_name = $attributeSetName;

        return $this;
    }

    /**
     * @return MongoProduct
     */
    public function getParent()
    {
        return $this->parent;
    }

    /**
     * @param MongoProduct $parent
     * @return $this
     */
    public function setParent($parent)
    {
        $this->parent = $parent;

        return $this;
    }

    /**
     * @return MongoProduct[]
     */
    public function getChildren()
    {
        return $this->children;
    }

    /**
     * @param MongoProduct[] $children
     * @return $this
     */
    public function setChildren($children)
    {
        $this->children = $children;

        return $this;
    }

    /**
     * @param Locale|null $locale
     * @return MongoValue[]
     */
    public function getValues(Locale $locale = null)
    {
        $result = new ArrayCollection();

        if ($locale instanceof Locale) {
            foreach ($this->values as $value) {
                if ($locale->getCode() == $value->getLocale()) {
                    $result->add($value);
                }
            }
        } else {
            $result = $this->values;
        }

        return $result;
    }

    /**
     * @param Locale|null $locale
     * @return MongoValue[]
     */
    public function getValuesMappedByAttribute(Locale $locale = null)
    {
        $result = [];
        foreach ($this->getValues($locale) as $value) {
            $result[$value->getAttribute()->getId()] = $value;
        }

        return $result;
    }

    /**
     * @param MongoValue[] $values
     * @return $this
     */
    public function setValues($values)
    {
        $this->values = $values;

        return $this;
    }

    /**
     * @param \DateTime $created
     * @return $this
     */
    public function setCreated(\DateTime $created)
    {
        $this->created = $created;

        return $this;
    }

    /**
     * @return array
     */
    static function getFieldNames()
    {
        try {
            $reflection = new ReflectionClass(MongoProduct::class);

            $result = array_column($reflection->getProperties(), 'name');
        } catch (\ReflectionException $e) {
            $result = [];
        }

        return $result;
    }
}
...