我似乎无法使用以下查询。基本上,我正在尝试将消息文档添加到对话文档中,如下所示:
public function reply($conversationId, Message $message, $flush = true)
{
$this->dm->createQueryBuilder($this->class)
->field('archivers')->unsetField()
->field('repliedBy')->set($message->getUserId())
->field('repliedBody')->set($message->getBody())
->field('repliedAt')->set(new \DateTime())
->field('modifiedAt')->set(new \DateTime())
->field('messages')->push($message)
->field('id')->equals(new \MongoId($conversationId))
->getQuery()
->execute();
if ($flush) {
$this->dm->flush();
}
}
此回复方法以两种方式调用。首先是用户通过html表单发布消息,然后是由Android应用程序发出的REST调用。表单有效但REST调用失败(其余实现使用带有FOSRestBundle btw的JMSSerializerBundle)...
我已经验证了代码被调用,并且传递给方法的参数在两种情况下都是有效的,但由于某种原因,UnitOfWork.php中的commit()调用忽略了对文档的更改。请参阅line 413了解我的意思。
有人知道为什么会这样吗?
以下是我尝试的其他方法:
首先,我添加了一个update()调用失败,其中包含“Catchable Fatal Error:类的对象...无法转换为/vendor/bundles/Symfony/Bundle/DoctrineMongoDBBundle/Logger/DoctrineMongoDBLogger.php行中的字符串280" 。
public function reply($conversationId, Message $message, $flush = true)
{
$this->dm->createQueryBuilder($this->class)
->update()
->field('archivers')->unsetField()
->field('repliedBy')->set($message->getUserId())
->field('repliedBody')->set($message->getBody())
->field('repliedAt')->set(new \DateTime())
->field('modifiedAt')->set(new \DateTime())
->field('messages')->push($message)
->field('id')->equals(new \MongoId($conversationId))
->getQuery()
->execute();
if ($flush) {
$this->dm->flush();
}
}
我尝试的第二种方法是推送数组而不是对象:
public function reply($conversationId, Message $message)
{
$this->dm->createQueryBuilder($this->class)
->update()
->field('archivers')->unsetField()
->field('repliedBy')->set($message->getUserId())
->field('repliedBody')->set($message->getBody())
->field('repliedAt')->set(new \DateTime())
->field('modifiedAt')->set(new \DateTime())
->field('messages')->push(array(
'_id' => new \MongoId(),
'userId' => $message->getuserId(),
'body' => $message->getBody(),
'createdAt' => new \DateTime(),
'modifiedAt' => new \DateTime(),
))
->field('id')->equals(new \MongoId($conversationId))
->getQuery()
->execute();
$this->dm->flush();
}
在调用flush()方法之前,它可以正常工作。 flush()导致重复的对象被推送。所以我在对话中得到了同一个消息的两个副本(注释flush()解决了问题但是应用程序在其他类中有多个flush()调用)。
另一个使用对象失败的推送查询:
public function archive($conversationId, $userId)
{
$userStamp = new UserStamp();
$userStamp->setUserId($userId);
$this->dm->createQueryBuilder($this->class)
->update()
->field('archivers')->push($userStamp)
->field('modifiedAt')->set(new \DateTime())
->field('id')->equals(new \MongoId($conversationId))
->getQuery()
->execute();
}
如果删除了push()调用,一切正常。
此时仍然停滞不前。
答案 0 :(得分:3)
查询构建器通常用于对MongoDB执行多文档或命令查询,后者绕过文档管理。唯一的例外是如果您正在执行水合查找查询,query builder documentation中对此进行了描述。您上面的示例等同于:
$collection->update(
['_id' => new \MongoId($conversationId)],
[
'$set' => [
'repliedBy' => $message->getUserId(),
'repliedBody' => $message->getbody(),
'repliedAt' => new \MongoDate(),
'modifiedAt' => new \MongoDate(),
],
'$push' => ['messages' => $message],
],
['multiple' => false]
);
请注意,您的字段映射将被使用(例如,Datetime将成为MongoDate),但没有要使用此查询管理的文档。
答案 1 :(得分:0)
如果在更新期间推送对象,请在php中使用\ stdClass。 快速示例:
public function reply($conversationId, Message $message)
{
$object = new \stdClass();
$object->_id = new \MongoId();
$object->userId = $message->getuserId();
$object->body = $message->getBody();
$object->createdAt = new \MongoDate();
$object->modifiedAt = new \MongoDate();
$this->dm->createQueryBuilder($this->class)
->update()
->field('archivers')->unsetField()
->field('repliedBy')->set($message->getUserId())
->field('repliedBody')->set($message->getBody())
->field('repliedAt')->set(new \DateTime())
->field('modifiedAt')->set(new \DateTime())
->field('messages')->push()
->field('id')->equals(new \MongoId($conversationId))
->getQuery()
->execute();
$this->dm->flush();
}