Mongodb Gedmo TIMESTABLE在使用JMS序列化程序反序列化时始终更新引用

Mongodb Gedmo TIMESTABLE在使用JMS序列化程序反序列化时始终更新引用,mongodb,symfony,doctrine-orm,jmsserializerbundle,jms-serializer,Mongodb,Symfony,Doctrine Orm,Jmsserializerbundle,Jms Serializer,我在我的Symfony2项目中有一对一的关系,问题引用了视频——两者都有一个创建和更新的Gedmo\timestable行为,基本上按照预期工作。但是有点太多了: 当将问题与所附的视频反序列化时(作为ID,仅用于避免视频元数据中的其他更改),视频文档始终在创建的和更新的字段上获得更新。这似乎不对。我可以理解为什么更新后的字段会有一个新的日期——即使对象本身没有任何变化,但为什么要创建 这是我的代码(简化): 课堂问题: <?php /** * Class Question * *

我在我的Symfony2项目中有一对一的关系,
问题
引用了
视频
——两者都有一个创建和更新的Gedmo\timestable行为,基本上按照预期工作。但是有点太多了:

当将
问题
与所附的
视频
反序列化时(作为ID,仅用于避免视频元数据中的其他更改),
视频
文档始终在
创建的
更新的
字段上获得更新。这似乎不对。我可以理解为什么更新后的字段会有一个新的日期——即使对象本身没有任何变化,但为什么要创建

这是我的代码(简化):

课堂问题:

<?php

/**
 * Class Question
 *
 * @Serializer\AccessorOrder("alphabetical")
 * @MongoDB\Document(
 *   collection="Quiz",
 *   repositoryClass="MyNamespace\Bundle\QuizBundle\Repository\QuestionRepository",
 * )
 * @package MyNamespace\Bundle\QuizBundle\Document
 */
class Question
{
    /**
     * @var \MongoId
     * @MongoDB\Id(strategy="auto")
     * @Serializer\Type("string")
     * @Serializer\Groups({
     *   "quiz_admin_list",
     *   "quiz_admin_detail"
     * })
     */
    protected $id;

    /**
     * @var \DateTime
     *
     * @Assert\Date(
     *   message = "quiz:constraints.model.question.created.invalid"
     * )
     * @Serializer\Type("DateTime<'U'>")
     * @Serializer\Accessor(getter="getCreated", setter="setCreatedEmpty")
     * @Serializer\Groups({
     *   "quiz_admin_list",
     *   "quiz_admin_detail"
     * })
     * @Gedmo\Timestampable(on="create")
     * @MongoDB\Date
     */
    protected $created;


    /**
     * @var \DateTime
     *
     * @Assert\Date(
     *   message = "quiz:constraints.model.question.updated.invalid"
     * )
     * @Serializer\Type("DateTime<'U'>")
     * @Serializer\Accessor(getter="getUpdated", setter="setUpdatedEmpty")
     * @Serializer\Groups({
     *   "quiz_admin_list",
     *   "quiz_admin_detail"
     * })
     * @Gedmo\Timestampable(on="update")
     * @MongoDB\Date
     */
    protected $updated;

    /**
     * @var Video
     *
     * @Serializer\Type("MyNamespace\Bundle\CoreMediaAdminBundle\Document\Video")
     * @Serializer\Groups({
     *   "quiz_admin_list",
     *   "quiz_admin_detail"
     * })
     * @MongoDB\ReferenceOne(
     *   targetDocument="MyNamespace\Bundle\CoreMediaAdminBundle\Document\Video",
     *   cascade={"all"}
     * )
     */
    protected $answerVideo;

}
查询:

db.QuizQuestion.find({
  "_id": ObjectId("547f31e650e56f2c26000063")
}).limit(1).limit();

db.CoreMediaAdminVideo.update({
  "_id": ObjectId("547f31d850e56f2c26000031")
},
{
  "$set": {
    "created": newISODate("2014-12-03T21:30:02+01:00"),
    "updated": newISODate("2014-12-03T21:30:02+01:00"),
    "updatedContent": newISODate("2014-12-03T21:30:02+01:00")
  }
});

db.ARDBuffetQuizQuestion.update({
  "_id": ObjectId("547f31e650e56f2c26000063")
},
{
  "$set": {
    "created": newISODate("2014-12-03T21:30:02+01:00"),
    "updated": newISODate("2014-12-03T21:30:02+01:00"),
    "questionText": "Wer einen Gemüsegarten hat, sollte wissen, dass Schnecken…?",
    "answerText": "test",
    "answerVideo": {
      "$ref": "CoreMediaAdminVideo",
      "$id": ObjectId("547f31d850e56f2c26000031"),
      "$db": "my-database"
    }
  }
});

db.ARDBuffetQuizQuestion.update({
  "_id": ObjectId("547f31e650e56f2c26000063")
},
{
  "$set": {
    "tags": [
      {
        "value": "Schnecken",
        "normalized": "schnecken"
      },
      {
        "value": "Basilikum",
        "normalized": "basilikum"
      },
      {
        "value": "Thymian",
        "normalized": "thymian"
      },
      {
        "value": "Garten",
        "normalized": "garten"
      }
    ]
  }
});

db.ARDBuffetQuizQuestion.find({
  "_id": ObjectId("547f31e650e56f2c26000063")
}).limit(1).limit();

db.CoreMediaAdminVideo.find({
  "_id": ObjectId("547f31d850e56f2c26000031")
}).limit(1).limit();

Gedmo\TIMESTABLE将为
$created
$updated
设置(新)值,因为刷新ObjectManager时不存在该数据

尽管类
Video
中的注释定义序列化此类对象时应包括
$created
$updated
,但显示的JSON不包含这些键/属性

下面是发生的情况:

  • JSON不包含键/属性
    创建的
    更新的
  • 反序列化时,结果对象将具有
    null
    值,用于
    $created
    $updated
  • merge()
    -将对象导入ObjectManager时,它不会发生任何变化。对象只是变为“托管”,这意味着在刷新期间,ObjectManager将为其计算更改集,并在必要时进行更新
  • 刷新ObjectManager时,Gedmo\TIMESTABLE将启动(由于
    PreUpdate
    事件侦听器)。它将看到
    $created
    $updated
    包含
    null
    值,因此它将分配新值
  • 然后ObjectManager将从数据库中检索“当前”数据,因为它需要它来计算更改集。通常,当
    find()
    -ing对象时,它不会这样做,因为在
    find()
    过程中已经检索到数据
  • 由于
    $created
    $updated
    的值现在与从数据库检索到的值不同,因此它将更新它们
因此,您将有两个选项:

  • find()
  • 确保JSON包含映射的所有属性(包括
    创建的
    更新的
  • 另外,我注意到
    setter=“setCreatedEmpty”
    setter=“setUpdatedEmpty”
    。我不确定这些方法是做什么的(因为您没有向我们展示),但是方法名称表明了一些简单赋值的东西

    回答你的意见 当
    merge()
    -将对象导入ObjectManager时,它被标记为“脏”,这将触发更改集的计算。而且由于DateTime对象的引用已更改(从db获得的实例始终不同于通过反序列化JSON创建的实例),因此对象将被更新。然后Gedmo\timestable将启动并相应地更改
    $updated
    属性


    如果不希望发生这种情况,则需要
    find()
    当前对象,并且只在值对象所代表的值实际更改时才更改它们。标量值没有问题:您可以设置相同的值,而条令不会将其视为更改。但对于值对象(如DateTime)对象,当引用发生更改时(当设置了不同的实例时),Doctrine将看到更改。

    您在查询中手动设置$set createdAt和updatedAt,或?tl;医生:你说得对。成功了。:)我使用的是
    setter=“setCreatedEmpty”
    ,因为在过去的一个项目(大约14个月前)中,我在doctrine mongodb&jms序列化程序中遇到了类似的问题,出于某种原因,没有在反序列化时再次设置创建/更新的值解决了这个问题。因此,我们只是简单地重复使用这个变通方法。现在,当所有数据都包含进来时,条令仍然会对引用的视频进行更新查询,但会保留您建议的原始
    创建的
    时间戳。我希望避免更多的疑问。不管怎样,它是有效的,不再有令人困惑的“创建”时间戳。谢谢。还有一个问题:当其他人更新视频并给它正确的新的更新时间戳时,这样做会再次覆盖更新的时间戳-所以100%确定,我应该从数据库中获取引用的对象并比较值,对吗或者,如果有一种方法可以避免额外的查询,那么这种情况就不会发生。。
    
    {
      "id": "547f31e650e56f2c26000063",
      "question_id": 12,
      "question_text": "Wer einen Gemüsegarten hat, sollte wissen, dass Schnecken…?",
      "answer_text": "test",
      "answer_video": {
        "id": "547f31d850e56f2c26000031"
      },
      "tags": [
        "Schnecken",
        "Basilikum",
        "Thymian",
        "Garten"
      ]
    }
    
    db.QuizQuestion.find({
      "_id": ObjectId("547f31e650e56f2c26000063")
    }).limit(1).limit();
    
    db.CoreMediaAdminVideo.update({
      "_id": ObjectId("547f31d850e56f2c26000031")
    },
    {
      "$set": {
        "created": newISODate("2014-12-03T21:30:02+01:00"),
        "updated": newISODate("2014-12-03T21:30:02+01:00"),
        "updatedContent": newISODate("2014-12-03T21:30:02+01:00")
      }
    });
    
    db.ARDBuffetQuizQuestion.update({
      "_id": ObjectId("547f31e650e56f2c26000063")
    },
    {
      "$set": {
        "created": newISODate("2014-12-03T21:30:02+01:00"),
        "updated": newISODate("2014-12-03T21:30:02+01:00"),
        "questionText": "Wer einen Gemüsegarten hat, sollte wissen, dass Schnecken…?",
        "answerText": "test",
        "answerVideo": {
          "$ref": "CoreMediaAdminVideo",
          "$id": ObjectId("547f31d850e56f2c26000031"),
          "$db": "my-database"
        }
      }
    });
    
    db.ARDBuffetQuizQuestion.update({
      "_id": ObjectId("547f31e650e56f2c26000063")
    },
    {
      "$set": {
        "tags": [
          {
            "value": "Schnecken",
            "normalized": "schnecken"
          },
          {
            "value": "Basilikum",
            "normalized": "basilikum"
          },
          {
            "value": "Thymian",
            "normalized": "thymian"
          },
          {
            "value": "Garten",
            "normalized": "garten"
          }
        ]
      }
    });
    
    db.ARDBuffetQuizQuestion.find({
      "_id": ObjectId("547f31e650e56f2c26000063")
    }).limit(1).limit();
    
    db.CoreMediaAdminVideo.find({
      "_id": ObjectId("547f31d850e56f2c26000031")
    }).limit(1).limit();