Query by reference in Doctrine ODM (Mongo)











up vote
0
down vote

favorite












History



Recreating mongo structure to combat memory issues in the former approach where a product is stored per locale and all values are an array hash (took to long to update).



Current problem



I can't seem to fetch products containing a referenced attribute with key "x" and value "y".



AggregationBuilder



This approach will give me only localized values (a product can contain 5000 values for 30 locales), it works and it is faster than a repositoryMethod on the getValues() in the Value document.



/**
* @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);
}


I wanted to use the same approach to continue to filter the values by checking their value and referenced attribute, for example;



I want all products (with values for locale: "en_GB") that matches with the statement below



referenced attribute for a value should be (screen_size) and must have value "16 inches"



it will return all products that match the attribute filtering with the localized values



Mongo Attribute



<?php

namespace MongoBundleDocument;

use DoctrineODMMongoDBMappingAnnotationsIndex;
use DoctrineODMMongoDBMappingAnnotations as MongoDB;

/**
* Class MongoAttribute
* @package MongoBundleDocument
*
* @MongoDBDocument(
* repositoryClass="MongoBundleDocumentRepositoryMongoAttributeRepository",
* indexes={@Index(keys={"code"="desc", "name"="desc"}, options={"unique"=true})}
* )
*/
class MongoAttribute
{
/**
* @var int
* @MongoDBId(strategy="NONE")
*/
private $id;

/**
* @var string
* @MongoDBField(type="string")
*/
private $code;

/**
* @var string
* @MongoDBField(type="string")
*/
private $name;

/**
* @var string
* @MongoDBField(type="string")
*/
private $type;

/**
* @var string
* @MongoDBField(type="string")
*/
private $pre_fix;

/**
* @var string
* @MongoDBField(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;
}
}


Mongo Value



<?php

namespace MongoBundleDocument;

use DoctrineODMMongoDBMappingAnnotationsIndex;
use DoctrineODMMongoDBMappingAnnotations as MongoDB;

/**
* Class MongoValue
* @package MongoBundleDocument
*
* @MongoDBDocument(repositoryClass="MongoBundleDocumentRepositoryMongoValueRepository",
* indexes={@Index(keys={"locale"="desc", "attribute"="desc", "id"="desc"}, options={"unique"=true})}
* )
*/
class MongoValue
{
/**
* @var int
* @MongoDBId(strategy="NONE")
*/
private $id;

/**
* @var string
* @MongoDBField(type="string")
*/
private $locale;

/**
* @var string
* @MongoDBField(type="string")
*/
private $value;

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

/**
* @var MongoProduct
* @MongoDBReferenceOne(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;
}
}


Mongo Product



<?php

namespace MongoBundleDocument;

use DoctrineCommonCollectionsArrayCollection;
use DoctrineODMMongoDBMappingAnnotations as MongoDB;
use DoctrineODMMongoDBMappingAnnotationsIndex;
use ReflectionClass;
use CatalogBundleEntityLocale;

/**
* Class MongoProduct
* @package MongoBundleDocument
*
* @MongoDBDocument(repositoryClass="MongoBundleDocumentRepositoryMongoProductRepository",
* indexes={@Index(keys={"id"="desc", "name"="desc"}, options={"unique"=true})}
* )
*/
class MongoProduct
{
/**
* @var integer
* @MongoDBId(strategy="NONE")
*/
protected $id;

/**
* @var string
* @MongoDBField(type="string")
*/
protected $name;

/**
* @var DateTime
* @MongoDBField(type="date")
*/
protected $created;

/**
* @var DateTime
* @MongoDBField(type="date")
*/
protected $updated;

/**
* @var boolean
* @MongoDBField(type="bool")
*/
protected $archived;

/**
* @var integer
* @MongoDBField(type="bool")
*/
protected $is_parent;

/**
* @var integer
* @MongoDBField(type="bool")
*/
protected $is_child;

/**
* @var boolean
* @MongoDBField(type="bool")
*/
protected $is_single;

/**
* @var string
* @MongoDBField(type="string")
*/
protected $attribute_set_id;

/**
* @var string
* @MongoDBField(type="string")
*/
protected $attribute_set_name;

/**
* @var MongoProduct
* @MongoDBReferenceOne(targetDocument="MongoProduct")
*/
protected $parent;

/**
* @var MongoProduct
* @MongoDBReferenceMany(targetDocument="MongoProduct", cascade={"persist"}, orphanRemoval=true)
*/
protected $children;

/**
* @var MongoValue
* @MongoDBReferenceMany(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;
}
}









share|improve this question
























  • It's hard to say what you're trying to achieve/what is going wrong with info provided. Also there's a lot of noise not connected with the question at hand (i.e. half of MongoProduct, accessors in other classes). Anyways, try playing with aggregation builder in console and "translate" it to ODM after you have working pipeline, it'll be easier that way.
    – malarzm
    12 hours ago















up vote
0
down vote

favorite












History



Recreating mongo structure to combat memory issues in the former approach where a product is stored per locale and all values are an array hash (took to long to update).



Current problem



I can't seem to fetch products containing a referenced attribute with key "x" and value "y".



AggregationBuilder



This approach will give me only localized values (a product can contain 5000 values for 30 locales), it works and it is faster than a repositoryMethod on the getValues() in the Value document.



/**
* @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);
}


I wanted to use the same approach to continue to filter the values by checking their value and referenced attribute, for example;



I want all products (with values for locale: "en_GB") that matches with the statement below



referenced attribute for a value should be (screen_size) and must have value "16 inches"



it will return all products that match the attribute filtering with the localized values



Mongo Attribute



<?php

namespace MongoBundleDocument;

use DoctrineODMMongoDBMappingAnnotationsIndex;
use DoctrineODMMongoDBMappingAnnotations as MongoDB;

/**
* Class MongoAttribute
* @package MongoBundleDocument
*
* @MongoDBDocument(
* repositoryClass="MongoBundleDocumentRepositoryMongoAttributeRepository",
* indexes={@Index(keys={"code"="desc", "name"="desc"}, options={"unique"=true})}
* )
*/
class MongoAttribute
{
/**
* @var int
* @MongoDBId(strategy="NONE")
*/
private $id;

/**
* @var string
* @MongoDBField(type="string")
*/
private $code;

/**
* @var string
* @MongoDBField(type="string")
*/
private $name;

/**
* @var string
* @MongoDBField(type="string")
*/
private $type;

/**
* @var string
* @MongoDBField(type="string")
*/
private $pre_fix;

/**
* @var string
* @MongoDBField(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;
}
}


Mongo Value



<?php

namespace MongoBundleDocument;

use DoctrineODMMongoDBMappingAnnotationsIndex;
use DoctrineODMMongoDBMappingAnnotations as MongoDB;

/**
* Class MongoValue
* @package MongoBundleDocument
*
* @MongoDBDocument(repositoryClass="MongoBundleDocumentRepositoryMongoValueRepository",
* indexes={@Index(keys={"locale"="desc", "attribute"="desc", "id"="desc"}, options={"unique"=true})}
* )
*/
class MongoValue
{
/**
* @var int
* @MongoDBId(strategy="NONE")
*/
private $id;

/**
* @var string
* @MongoDBField(type="string")
*/
private $locale;

/**
* @var string
* @MongoDBField(type="string")
*/
private $value;

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

/**
* @var MongoProduct
* @MongoDBReferenceOne(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;
}
}


Mongo Product



<?php

namespace MongoBundleDocument;

use DoctrineCommonCollectionsArrayCollection;
use DoctrineODMMongoDBMappingAnnotations as MongoDB;
use DoctrineODMMongoDBMappingAnnotationsIndex;
use ReflectionClass;
use CatalogBundleEntityLocale;

/**
* Class MongoProduct
* @package MongoBundleDocument
*
* @MongoDBDocument(repositoryClass="MongoBundleDocumentRepositoryMongoProductRepository",
* indexes={@Index(keys={"id"="desc", "name"="desc"}, options={"unique"=true})}
* )
*/
class MongoProduct
{
/**
* @var integer
* @MongoDBId(strategy="NONE")
*/
protected $id;

/**
* @var string
* @MongoDBField(type="string")
*/
protected $name;

/**
* @var DateTime
* @MongoDBField(type="date")
*/
protected $created;

/**
* @var DateTime
* @MongoDBField(type="date")
*/
protected $updated;

/**
* @var boolean
* @MongoDBField(type="bool")
*/
protected $archived;

/**
* @var integer
* @MongoDBField(type="bool")
*/
protected $is_parent;

/**
* @var integer
* @MongoDBField(type="bool")
*/
protected $is_child;

/**
* @var boolean
* @MongoDBField(type="bool")
*/
protected $is_single;

/**
* @var string
* @MongoDBField(type="string")
*/
protected $attribute_set_id;

/**
* @var string
* @MongoDBField(type="string")
*/
protected $attribute_set_name;

/**
* @var MongoProduct
* @MongoDBReferenceOne(targetDocument="MongoProduct")
*/
protected $parent;

/**
* @var MongoProduct
* @MongoDBReferenceMany(targetDocument="MongoProduct", cascade={"persist"}, orphanRemoval=true)
*/
protected $children;

/**
* @var MongoValue
* @MongoDBReferenceMany(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;
}
}









share|improve this question
























  • It's hard to say what you're trying to achieve/what is going wrong with info provided. Also there's a lot of noise not connected with the question at hand (i.e. half of MongoProduct, accessors in other classes). Anyways, try playing with aggregation builder in console and "translate" it to ODM after you have working pipeline, it'll be easier that way.
    – malarzm
    12 hours ago













up vote
0
down vote

favorite









up vote
0
down vote

favorite











History



Recreating mongo structure to combat memory issues in the former approach where a product is stored per locale and all values are an array hash (took to long to update).



Current problem



I can't seem to fetch products containing a referenced attribute with key "x" and value "y".



AggregationBuilder



This approach will give me only localized values (a product can contain 5000 values for 30 locales), it works and it is faster than a repositoryMethod on the getValues() in the Value document.



/**
* @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);
}


I wanted to use the same approach to continue to filter the values by checking their value and referenced attribute, for example;



I want all products (with values for locale: "en_GB") that matches with the statement below



referenced attribute for a value should be (screen_size) and must have value "16 inches"



it will return all products that match the attribute filtering with the localized values



Mongo Attribute



<?php

namespace MongoBundleDocument;

use DoctrineODMMongoDBMappingAnnotationsIndex;
use DoctrineODMMongoDBMappingAnnotations as MongoDB;

/**
* Class MongoAttribute
* @package MongoBundleDocument
*
* @MongoDBDocument(
* repositoryClass="MongoBundleDocumentRepositoryMongoAttributeRepository",
* indexes={@Index(keys={"code"="desc", "name"="desc"}, options={"unique"=true})}
* )
*/
class MongoAttribute
{
/**
* @var int
* @MongoDBId(strategy="NONE")
*/
private $id;

/**
* @var string
* @MongoDBField(type="string")
*/
private $code;

/**
* @var string
* @MongoDBField(type="string")
*/
private $name;

/**
* @var string
* @MongoDBField(type="string")
*/
private $type;

/**
* @var string
* @MongoDBField(type="string")
*/
private $pre_fix;

/**
* @var string
* @MongoDBField(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;
}
}


Mongo Value



<?php

namespace MongoBundleDocument;

use DoctrineODMMongoDBMappingAnnotationsIndex;
use DoctrineODMMongoDBMappingAnnotations as MongoDB;

/**
* Class MongoValue
* @package MongoBundleDocument
*
* @MongoDBDocument(repositoryClass="MongoBundleDocumentRepositoryMongoValueRepository",
* indexes={@Index(keys={"locale"="desc", "attribute"="desc", "id"="desc"}, options={"unique"=true})}
* )
*/
class MongoValue
{
/**
* @var int
* @MongoDBId(strategy="NONE")
*/
private $id;

/**
* @var string
* @MongoDBField(type="string")
*/
private $locale;

/**
* @var string
* @MongoDBField(type="string")
*/
private $value;

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

/**
* @var MongoProduct
* @MongoDBReferenceOne(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;
}
}


Mongo Product



<?php

namespace MongoBundleDocument;

use DoctrineCommonCollectionsArrayCollection;
use DoctrineODMMongoDBMappingAnnotations as MongoDB;
use DoctrineODMMongoDBMappingAnnotationsIndex;
use ReflectionClass;
use CatalogBundleEntityLocale;

/**
* Class MongoProduct
* @package MongoBundleDocument
*
* @MongoDBDocument(repositoryClass="MongoBundleDocumentRepositoryMongoProductRepository",
* indexes={@Index(keys={"id"="desc", "name"="desc"}, options={"unique"=true})}
* )
*/
class MongoProduct
{
/**
* @var integer
* @MongoDBId(strategy="NONE")
*/
protected $id;

/**
* @var string
* @MongoDBField(type="string")
*/
protected $name;

/**
* @var DateTime
* @MongoDBField(type="date")
*/
protected $created;

/**
* @var DateTime
* @MongoDBField(type="date")
*/
protected $updated;

/**
* @var boolean
* @MongoDBField(type="bool")
*/
protected $archived;

/**
* @var integer
* @MongoDBField(type="bool")
*/
protected $is_parent;

/**
* @var integer
* @MongoDBField(type="bool")
*/
protected $is_child;

/**
* @var boolean
* @MongoDBField(type="bool")
*/
protected $is_single;

/**
* @var string
* @MongoDBField(type="string")
*/
protected $attribute_set_id;

/**
* @var string
* @MongoDBField(type="string")
*/
protected $attribute_set_name;

/**
* @var MongoProduct
* @MongoDBReferenceOne(targetDocument="MongoProduct")
*/
protected $parent;

/**
* @var MongoProduct
* @MongoDBReferenceMany(targetDocument="MongoProduct", cascade={"persist"}, orphanRemoval=true)
*/
protected $children;

/**
* @var MongoValue
* @MongoDBReferenceMany(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;
}
}









share|improve this question















History



Recreating mongo structure to combat memory issues in the former approach where a product is stored per locale and all values are an array hash (took to long to update).



Current problem



I can't seem to fetch products containing a referenced attribute with key "x" and value "y".



AggregationBuilder



This approach will give me only localized values (a product can contain 5000 values for 30 locales), it works and it is faster than a repositoryMethod on the getValues() in the Value document.



/**
* @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);
}


I wanted to use the same approach to continue to filter the values by checking their value and referenced attribute, for example;



I want all products (with values for locale: "en_GB") that matches with the statement below



referenced attribute for a value should be (screen_size) and must have value "16 inches"



it will return all products that match the attribute filtering with the localized values



Mongo Attribute



<?php

namespace MongoBundleDocument;

use DoctrineODMMongoDBMappingAnnotationsIndex;
use DoctrineODMMongoDBMappingAnnotations as MongoDB;

/**
* Class MongoAttribute
* @package MongoBundleDocument
*
* @MongoDBDocument(
* repositoryClass="MongoBundleDocumentRepositoryMongoAttributeRepository",
* indexes={@Index(keys={"code"="desc", "name"="desc"}, options={"unique"=true})}
* )
*/
class MongoAttribute
{
/**
* @var int
* @MongoDBId(strategy="NONE")
*/
private $id;

/**
* @var string
* @MongoDBField(type="string")
*/
private $code;

/**
* @var string
* @MongoDBField(type="string")
*/
private $name;

/**
* @var string
* @MongoDBField(type="string")
*/
private $type;

/**
* @var string
* @MongoDBField(type="string")
*/
private $pre_fix;

/**
* @var string
* @MongoDBField(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;
}
}


Mongo Value



<?php

namespace MongoBundleDocument;

use DoctrineODMMongoDBMappingAnnotationsIndex;
use DoctrineODMMongoDBMappingAnnotations as MongoDB;

/**
* Class MongoValue
* @package MongoBundleDocument
*
* @MongoDBDocument(repositoryClass="MongoBundleDocumentRepositoryMongoValueRepository",
* indexes={@Index(keys={"locale"="desc", "attribute"="desc", "id"="desc"}, options={"unique"=true})}
* )
*/
class MongoValue
{
/**
* @var int
* @MongoDBId(strategy="NONE")
*/
private $id;

/**
* @var string
* @MongoDBField(type="string")
*/
private $locale;

/**
* @var string
* @MongoDBField(type="string")
*/
private $value;

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

/**
* @var MongoProduct
* @MongoDBReferenceOne(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;
}
}


Mongo Product



<?php

namespace MongoBundleDocument;

use DoctrineCommonCollectionsArrayCollection;
use DoctrineODMMongoDBMappingAnnotations as MongoDB;
use DoctrineODMMongoDBMappingAnnotationsIndex;
use ReflectionClass;
use CatalogBundleEntityLocale;

/**
* Class MongoProduct
* @package MongoBundleDocument
*
* @MongoDBDocument(repositoryClass="MongoBundleDocumentRepositoryMongoProductRepository",
* indexes={@Index(keys={"id"="desc", "name"="desc"}, options={"unique"=true})}
* )
*/
class MongoProduct
{
/**
* @var integer
* @MongoDBId(strategy="NONE")
*/
protected $id;

/**
* @var string
* @MongoDBField(type="string")
*/
protected $name;

/**
* @var DateTime
* @MongoDBField(type="date")
*/
protected $created;

/**
* @var DateTime
* @MongoDBField(type="date")
*/
protected $updated;

/**
* @var boolean
* @MongoDBField(type="bool")
*/
protected $archived;

/**
* @var integer
* @MongoDBField(type="bool")
*/
protected $is_parent;

/**
* @var integer
* @MongoDBField(type="bool")
*/
protected $is_child;

/**
* @var boolean
* @MongoDBField(type="bool")
*/
protected $is_single;

/**
* @var string
* @MongoDBField(type="string")
*/
protected $attribute_set_id;

/**
* @var string
* @MongoDBField(type="string")
*/
protected $attribute_set_name;

/**
* @var MongoProduct
* @MongoDBReferenceOne(targetDocument="MongoProduct")
*/
protected $parent;

/**
* @var MongoProduct
* @MongoDBReferenceMany(targetDocument="MongoProduct", cascade={"persist"}, orphanRemoval=true)
*/
protected $children;

/**
* @var MongoValue
* @MongoDBReferenceMany(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;
}
}






mongodb doctrine odm






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 18 hours ago

























asked 20 hours ago









SinisterGlitch

30218




30218












  • It's hard to say what you're trying to achieve/what is going wrong with info provided. Also there's a lot of noise not connected with the question at hand (i.e. half of MongoProduct, accessors in other classes). Anyways, try playing with aggregation builder in console and "translate" it to ODM after you have working pipeline, it'll be easier that way.
    – malarzm
    12 hours ago


















  • It's hard to say what you're trying to achieve/what is going wrong with info provided. Also there's a lot of noise not connected with the question at hand (i.e. half of MongoProduct, accessors in other classes). Anyways, try playing with aggregation builder in console and "translate" it to ODM after you have working pipeline, it'll be easier that way.
    – malarzm
    12 hours ago
















It's hard to say what you're trying to achieve/what is going wrong with info provided. Also there's a lot of noise not connected with the question at hand (i.e. half of MongoProduct, accessors in other classes). Anyways, try playing with aggregation builder in console and "translate" it to ODM after you have working pipeline, it'll be easier that way.
– malarzm
12 hours ago




It's hard to say what you're trying to achieve/what is going wrong with info provided. Also there's a lot of noise not connected with the question at hand (i.e. half of MongoProduct, accessors in other classes). Anyways, try playing with aggregation builder in console and "translate" it to ODM after you have working pipeline, it'll be easier that way.
– malarzm
12 hours ago

















active

oldest

votes











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














 

draft saved


draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53372060%2fquery-by-reference-in-doctrine-odm-mongo%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown






























active

oldest

votes













active

oldest

votes









active

oldest

votes






active

oldest

votes
















 

draft saved


draft discarded



















































 


draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53372060%2fquery-by-reference-in-doctrine-odm-mongo%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Can a sorcerer learn a 5th-level spell early by creating spell slots using the Font of Magic feature?

Does disintegrating a polymorphed enemy still kill it after the 2018 errata?

A Topological Invariant for $pi_3(U(n))$