Symfony QueryBuilder returning MongoDB cursor inst

2019-09-06 23:48发布

问题:

I am trying to build a custom querying function returning MongoDB documents corresponding to some filters. I have created this function into a specific repository for my document User:

namespace LogAnalyzer\CoreBundle\Repository;

use Doctrine\ODM\MongoDB\DocumentRepository;

class UserRepository extends DocumentRepository
{
    public function getUserTemp($clauses = null)
    {
        /* Create query */

        $query = $this -> createQueryBuilder();

        /* Add clauses */

        if($clauses)
        {
            if(isset($clauses['id']))
                $query -> field('id') -> equals($clauses['id']);

            if(isset($clauses['firstName']))
                $query -> field('firstName') -> equals($clauses['firstName']);

            if(isset($clauses['lastName']))
                $query -> field('lastName') -> equals($clauses['lastName']);

            if(isset($clauses['email']))
                $query -> field('email') -> equals($clauses['email']);

            if(isset($clauses['password']))
                $query -> field('password') -> equals($clauses['password']);
        }

        /* Return */

        return $query
            -> getQuery()
            -> execute();
    }
}

Here is the definition of my User document:

namespace LogAnalyzer\CoreBundle\Document;

use JsonSerializable;
use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * @MongoDB\Document(repositoryClass="LogAnalyzer\CoreBundle\Repository\UserRepository")
 */
class User implements JsonSerializable
{
    /**
     * @MongoDB\Id
     */
    protected $id;

    /**
     * @MongoDB\String
     */
    protected $firstName;

    /**
     * @MongoDB\String
     */
    protected $lastName;

    /**
     * @MongoDB\String
     */
    protected $email;

    /**
     * @MongoDB\String
     */
    protected $password;

    ...
}

In my controller I have the private function using the querying function:

private function getUserAction()
{
    $manager = $this -> get('doctrine_mongodb') -> getManager();
    $repository = $manager -> getRepository('LogAnalyzerCoreBundle:User');

    $users = $repository -> getUserTemp(array(
        'firstName' => 'First'
    ));

    return $users;
}

When I run the function, I do not get an array of objects as expected but a Doctrine\ODM\MongoDB\Cursor instead.

Where is my error ?

EDIT:

Should I use -> toArray(false) ?

Thanks.

回答1:

You need the Eager MongoDB cursor to iterate queries. I'm gonna edit your code to make it easier for you:

class UserRepository extends DocumentRepository {
    public function getUserTemp($clauses = null)
    {
        /* Create query */

        $qb = $this->createQueryBuilder()->eagerCursor(true);

        /* Add clauses */

        if($clauses)
        {
            // It's a way to initialize the query, you can use a select or something similar
            $query = $qb->hydrate(true);

            if(isset($clauses['id']))
                $query -> field('id') -> equals($clauses['id']);

            if(isset($clauses['firstName']))
                $query -> field('firstName') -> equals($clauses['firstName']);

            if(isset($clauses['lastName']))
                $query -> field('lastName') -> equals($clauses['lastName']);

            if(isset($clauses['email']))
                $query -> field('email') -> equals($clauses['email']);

            if(isset($clauses['password']))
                $query -> field('password') -> equals($clauses['password']);
        }

        /* Return */

        return $query
            -> getQuery()
            -> execute();
    }
}

Now you can iterate the result with all results as objects inside.

private function getUserAction()
{
    $manager = $this -> get('doctrine_mongodb') -> getManager();
    $repository = $manager -> getRepository('LogAnalyzerCoreBundle:User');

    $users = $repository -> getUserTemp(array(
        'firstName' => 'First'
    ));
    //It's just an example, but here you can see how to get the query result data
    foreach($users as $user){
        $data[] = $user->getFirstName();
    }

    return $users;
}

It's the best way to do this, sometimes calling toArray() method is enough, but not always work.