Mongodb Gedmo TIMESTABLE在使用JMS序列化程序反序列化时始终更新引用
我在我的Symfony2项目中有一对一的关系,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 * *
问题
引用了视频
——两者都有一个创建和更新的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();