i'm having trouble persisting data using EmbedMany and strategy addToSet .
Reference:
https://www.doctrine-project.org/projects/doctrine-mongodb-odm/en/2.2/reference/storage-strategies.html https://www.doctrine-project.org/projects/doctrine-mongodb-odm/en/2.2/reference/embedded-mapping.html#embed_many
When adding more than one Consumer to the embedded collection, the data persistent is not coherent, and also the strategy addToSet that prevents duplicates does not work properly.
The main reason is to append data to consumers embedded collection without duplicates
Example:
consumers is empty [ ]
The classes that i'm using:
Doctrine Mapping
<!-- DomainObjectConsumer.mongodb.xml-->
<doctrine-mongo-mapping xmlns="http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping
https://doctrine-project.org/schemas/odm/doctrine-mongo-mapping.xsd">
<document name="DomainObjectConsumer">
<id strategy="NONE"/>
<field name="consumer" field-name="consumer" type="string"/>
</document>
</doctrine-mongo-mapping>
<!-- DomainObjectLog.mongodb.xml-->
<doctrine-mongo-mapping xmlns="http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping
https://doctrine-project.org/schemas/odm/doctrine-mongo-mapping.xsd">
<document
name="DomainObjectLog"
collection="domain_object_log"
repository-class="DomainObjectLogRepository">
<id strategy="auto"/>
<embed-many field="consumers"
strategy="addToSet"
target-document="DomainObjectConsumer"/>
</document>
</doctrine-mongo-mapping>
Domain Layer
<?php
class DomainObjectLog
{
/** @var string|null */
private $id;
/**
* @var ArrayCollection
*/
private $consumers;
public function __construct(?string $consumer)
{
$this->consumers = new ArrayCollection();
if ($consumer) {
$objectConsumer = new DomainObjectConsumer($consumer);
$this->addConsumer($objectConsumer);
}
}
/**
* @param DomainObjectConsumer $consumer
* @return DomainObjectLog
*/
public function addConsumer(DomainObjectConsumer $consumer): DomainObjectLog
{
$this->consumers->add($consumer);
return $this;
}
/** getters & setters **/
}
<?php
class DomainObjectConsumer
{
/** @var string|null */
private $id;
/**
* @var string
*/
private $consumer;
public function __construct(string $consumer)
{
$this->id = $consumer; // _id could make objects different ?
$this->consumer = $consumer;
}
/**
* @param string $consumer
* @return DomainObjectConsumer
*/
public function setConsumer(string $consumer): DomainObjectConsumer
{
$this->consumer = $consumer;
return $this;
}
/** getters & setters **/
}
Use Case scenario: Save
<?php
class SaveDomainObjectLog
{
public function save(string $uuid, ?string $consumer)
{
$objectLog = $this->objectLogRepository->getByUUID($uuid);
if (!$objectLog) {
$objectLog = new DomainObjectLog($consumer);
} else {
if (!is_null($consumer)) {
$objectConsumer = new DomainObjectConsumer($consumer);
$objectLog->addConsumer($objectConsumer);
}
}
$this->objectLogRepository->saveDomainObjectLog($objectLog);
}
}
Persistence layer is just saving the object $objectLog as is.
The behaviour goes like this:
first call to save with parameter consumer = CRM:
second call to save with parameter consumer = CRM:
third call to save with parameter consumer = CRM:
The expected result should be just: [{"_id": "CRM", "consumer": "CRM"}] after any call with the same consumer name.
Is there any reason why this is happening?
Why the persisted data is different?
and why addToSet is not working removing duplicates ?
Thanks in advance.
EDIT 1:
Traces from doctrine:
"update":"domain_object_log" .... "u":{"$set":{"consumers.1.consumer":"CRM"}}
"update":"domain_object_log" .... "u":{"$addToSet":{"consumers":{"$each":[{"_id":"CRM","consumer":"CRM"}]}}}
Expected behaviuor:
db.domain_object_log.updateOne({
"uuid":"12345678-1234-1234-1234-123f56780054"
},
{
"$addToSet":{
"consumers":{
"_id":"CRM",
"consumer":"CRM"
}
}
})
Found the solution:
The embedded document must be declared also as embedded in the xml file. This way you can remove the Id field.
<!-- DomainObjectConsumer.mongodb.xml-->
<doctrine-mongo-mapping xmlns="http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping
https://doctrine-project.org/schemas/odm/doctrine-mongo-mapping.xsd">
<embedded-document name="DomainObjectConsumer">
<field name="consumer" field-name="consumer" type="string"/>
</embedded-document>
</doctrine-mongo-mapping>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.