5

我似乎无法使以下查询起作用。基本上,我正在尝试将消息文档添加到对话文档中,如下所示:

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 调用失败(其余实现使用 JMSSerializerBundle 和 FOSRestBundle 顺便说一句)......

我已经验证了代码被调用并且传递给方法的参数在这两种情况下都是有效的,但是由于某种原因,UnitOfWork.php 中的 commit() 调用忽略了对文档的更改。请参阅第 413 行以了解我的意思。

有谁知道为什么会发生这种情况?

以下是我尝试过的其他方法:

首先,我添加了一个 update() 调用,该调用失败并显示“可捕获的致命错误:类的对象......无法在 /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() 调用被删除,一切正常。

仍然停留在这一点上。

4

2 回答 2

3

查询构建器通常用于对 MongoDB 执行多文档或命令查询,从而绕过文档管理。唯一的例外是,如果您正在执行查询生成器文档中描述的混合查找查询。您上面的示例等效于:

$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),但没有要使用此查询管理的文档。

于 2012-08-01T15:16:17.153 回答
0

如果在更新期间推送对象,请在 php.ini 中使用 \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();
}
于 2013-05-29T16:39:28.210 回答