doctrine manyToMany Query on Inverse Side - doctrine-orm

I've got 2 entity with Many To Many Relationship. They are Mapped correctly, both sides.
When I'm querying the inverse side with an Entity of the Owning side I've got the following error:
ContextErrorException: Notice: Undefined index: joinColumns in /var/www/symfony/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php line 1528
I'm using the "built-in" doctrine findBy Methods, in this case: "findByInverseSide($InverseSideEntity)"

I solve this By creating a DQL query with Left Join on the InverseSide of The Table:
EX:
...
$qb = $this->createQueryBuilder('q');
$qb->leftJoin('q.inverseSide', 'i')
->where('i.id = :inverseSide_id')
->setParameter('inverseSide_id', $inverseSide_id);
...

Related

Annotate A object with the count of related B objects with Subquery

I am trying to annotate User with the count of delayed leads objects. The calculation of delayed leads is complex (uses RawSQL) implemented using a custom model manager. Hence, I am trying to implement this using a subquery.
sq = Lead.delayed.filter(assigned_to_id=OuterRef('pk'))
User.objects.annotate(num=Count(Subquery(sq.count())))
However, I keep getting this error:
ValueError: This queryset contains a reference to an outer query and may only be used in a subquery.
UPDATE:
I tried adding only('id') so my code:
sq = Lead.delayed.filter(assigned_to_id=OuterRef('id')).only('id')
User.objects.annotate(num=Count(Subquery(sq)))
This generated the sql query:
SELECT `auth_user`.`id`, `auth_user`.`username`, `auth_user`.`first_name`,
`auth_user`.`last_name`, COUNT((SELECT U0.`id` FROM
`lead` U0 WHERE U0.`assigned_to_id` = (`auth_user`.`id`))) AS `count`
FROM `auth_user` GROUP BY `auth_user`.`id`;
This is throwing error:
ERROR 1242 (21000): Subquery returns more than 1 row
I would like to have my query generated as:
SELECT `auth_user`.`id`, `auth_user`.`username`, `auth_user`.`first_name`,
`auth_user`.`last_name`, (SELECT COUNT(U0.`id`) FROM `marketing_lead` U0 WHERE
(more complex conditions here) U0.`assigned_to_id` = (`auth_user`.`id`)) AS `count`
FROM `auth_user` GROUP BY `auth_user`.`id`;
How can I acheive that using django ORM?
Alternative question label might be How to use Count() not perform grouping (GROUP BY) or How to count all in a Subquery
Check this answer for custom Count function to just perform simple count on any queryset without grouping.
Unfortunately, so far haven't found native django option for this.
Though the answer from Oleg was quite close to my requirement but I was still getting an SQL error on the query generated by django. Hence, I ended up implementing using cursor.

Doctrine JOIN syntax

I'm having an issue converting some legacy SQL for the doctrine query builder. I think the problem is in the inner join, but I can't quite work out the parameters the builder is expecting.
This is what I have so far:
$qb = $em->createQueryBuilder();
$qb->select('ob.size', 'ob.colour', 'ob.productId', 'p.title')
->from('m:Option', 'ob')
->innerJoin('m:Product', 'p', 'ON', 'ob.ProductId');
And this is the original query:
query="select size,colour,product_id,title from
products,options_new where
picture = '' and
products.id = options_new.product_id and
product_id like 'UTRW%'
group by product_id";
I normally write joins explicitly, so I'm not certain I'm understanding how the from clause is working here.
At the moment the new query is generating this error:
Expected Doctrine\ORM\Query\Lexer::T_WITH, got 'ON'
Cheers!
Try the query below (drop here your entities, would be more helpful) and for more details about fetching related entities, check the docs: http://doctrine-orm.readthedocs.org/en/latest/reference/dql-doctrine-query-language.html#joins
$qb = $em->createQueryBuilder('m');
$qb->select('ob.size', 'ob.colour', 'ob.productId', 'p.title')
->innerJoin('m.product', 'ob');

How to reference elements from a joined table in a DQL statement

I have two entities (AdminMembers\Entity\Members and AdminEvents\Entity\Invitees) that are joined with a OneToMany relationship. Because the relationship is defined in the entities, I can use the following DQL statement to query the data:
$dql = "SELECT i FROM AdminEvents\Entity\Invitees i WHERE i.eventID=$eventID";
And, through this configuration I can use statements like $invitee->getMember()->getMemberLastName() in my ZF2 view script to get the data from the joined entities.
Now, if I want to sort the data in the DQL statement by fields in AdminMembers\Entity\Members, I run into a problem. The following statement
$dql = "SELECT i FROM AdminEvents\Entity\Invitees i WHERE i.eventID=$eventID ORDER BY i.memberLastName, i.memberFirstName";
throws the error message
Class AdminEvents\Entity\Invitees has no field or association named memberLastName
This is because the fields memberLastName and memberFirstName are defined in AdminMembers\Entity\Members. Although an association does exist, I'm certain I’m just missing some syntax in referencing memberLastName and memberFirstName.
I know that I can expand the DQL statement to join the entities in the DQL statement, which would allow me to identify the joined table and relate the elements to table identifier. But, since the tables are already joined in the entity definitions, they shouldn’t have to be joined again.
Is there a special syntax for referencing joined-table entities in the DQL statement without "rejoining" the tables in the statement?
You should join the members entity to be able to sort by its fields. See docs:
$dql = "SELECT i, m FROM AdminEvents\Entity\Invitees i JOIN i.member m WHERE i.eventID=$eventID ORDER BY m. memberLastName, m.memberFirstName";

Preventing lazy-loading gives me 1 "subentity"

I have a problem with Doctrine (Symfony2.1). I want to prevent lazy-loading by join fetching subentities (OneToMany relation) but I got only one result for those subentities.
For example:
public function getSingleProjectQuery($project){
$query = $this->createQueryBuilder('p')
->select(array("p", "fb"))
->where('p.id = :project_id')->setParameter('project_id', $project)
->leftJoin('p.feedbacks', 'fb')
->groupBy('p.id')
->getQuery();
return $query;
}
In this example Doctrine returns me the "Project"-object and one single "feedback" object (but there are more than one feedbacks...).
When I replace the select to this: ->select(array("p"))
I got all the "Feedback" objects but there are then lazy-loaded (many queries).
see http://docs.doctrine-project.org/en/latest/reference/dql-doctrine-query-language.html#joins
You should remove the groupBy clause.

Doctrine join filter

I know conditional filters aren't yet available for queries (as per "26.1.4. Applying Filter Rules to any Query" in the Known Limitations section of the Doctrine2 manual) , so I wanted to ask the experts what their preferred solution to the following problem is:
My site has product objects that each have many reviews. The reviews have a status field. I don't want to unnecessarily pull in reviews that haven't been approved during the automatic association that Doctrine2 does so wonderfully.
My current solution/hack is to use single table inheritance (STI) with a discriminator for "status" and have an ApprovedProductReview extending the ProductReview class based on a status of "APPROVED"
I should add that I am currently simply calling
$em->find('Entities\Product', $pid);
to get my product, and Doctrine2 does all the associations automatically. Should I instead be instantiating a product by providing a DQL query?
What I'd really like is a way to override the magic that Doctrine2 provides based on the annotations, and simply be able to use DQL to lazily get the correct subset of reviews.
Suggestions?
You can use the WITH statement in DQL:
$dql = "SELECT p, r
FROM Entities\Product p
LEFT JOIN p.reviews r WITH r.status = :status
WHERE p.id = :id"
$q = $em->createQuery($dql);
$q->setParameter('id', $id);
$q->setParameter('status', $status);
$product = $q->getSingleResult();