簡體   English   中英

使用doctrine-mongodb EmbedMany 策略addToSet 持久化數據時出錯

[英]Error persisting data with doctrine-mongodb EmbedMany strategy addToSet

我在使用EmbedMany和策略addToSet持久化數據時遇到問題。

參考:

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

在嵌入集合中添加多個 Consumer 時,數據持久化不連貫,防止重復的策略 addToSet 也無法正常工作。

主要原因是將數據附加到消費者嵌入的集合中而沒有重復

例子:

消費者為空 [ ]

  1. 添加消費者“CRM” -> 消費者 = [{'_id': "CRM", "consumer": "CRM"}]
  2. 添加消費者 "HS" -> 消費者 = [{'_id': "CRM", "consumer": "CRM"}, {'_id': "HS", "consumer": "HS"}]
  3. 再次添加這些消費者中的任何一個都不會向消費者嵌入的集合中添加新數據

我正在使用的課程:

教義映射

<!-- 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>

領域層

<?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 **/
}

用例場景:保存

<?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);
    }

}

持久層只是按原樣保存對象 $objectLog。

行為是這樣的:

第一次調用以參數消費者 = CRM 保存:

  • 現場消費者:[{“_id”:“CRM”,“消費者”:“CRM”}]

第二次調用以參數消費者 = CRM 保存:

  • 現場消費者:[{“_id”:“CRM”,“消費者”:“CRM”},{“消費者”:“CRM”}]

第三次調用以參數消費者 = CRM 保存:

  • 現場消費者:[{“_id”:“CRM”,“消費者”:“CRM”},{“消費者”:“CRM”},{“消費者”:“CRM”}]

預期結果應該是: [{"_id": "CRM", "consumer": "CRM"}] 在任何具有相同消費者名稱的調用之后。

發生這種情況有什么原因嗎?

為什么持久化的數據不同?

為什么 addToSet 不能刪除重復項?

提前致謝。

編輯 1:

教義的痕跡:

"update":"domain_object_log" .... "u":{"$set":{"consumers.1.consumer":"CRM"}}
"update":"domain_object_log" .... "u":{"$addToSet":{"consumers":{"$each":[{"_id":"CRM","consumer":"CRM"}]}}}

預期行為:

db.domain_object_log.updateOne({
   "uuid":"12345678-1234-1234-1234-123f56780054"
},
{
   "$addToSet":{
      "consumers":{
         "_id":"CRM",
         "consumer":"CRM"
      }
   }
})

找到了解決辦法:

嵌入的文檔也必須聲明為嵌入在 xml 文件中。 這樣您就可以刪除 Id 字段。

<!-- 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>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM