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

このreplyメソッドは2つの方法で呼び出されます。最初にユーザーがhtmlフォームを介してメッセージを投稿し、次にAndroidアプリケーションによって行われたREST呼び出しによって。フォームは機能しますが、REST呼び出しは失敗します(残りの実装はFOSRestBundleでJMSSerializerBundleを使用します)...

コードが呼び出され、メソッドに渡されたパラメーターがどちらの場合も有効であることを確認しましたが、何らかの理由で、UnitOfWork.php内のcommit()呼び出しはドキュメントへの変更を無視します。私が何を意味するかについては、413行目を参照してください。

なぜこれが起こっているのか誰かが知っていますか?

以下は私が試した他のアプローチです:

最初に、「Catchable Fatal Error:Object of class ... could not convert to string in /vendor/bundles/Symfony/Bundle/DoctrineMongoDBBundle/Logger/DoctrineMongoDBLogger.php line 280」で失敗するupdate()呼び出しを追加しました。

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

私が試した2番目のアプローチは、オブジェクトの代わりに配列をプッシュすることでした。

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()により、重複するオブジェクトがプッシュされます。そのため、会話で同じメッセージの2つのコピーを取得します(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で\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 に答える