Reputation: 490
I have 2 entities with same one to one relation:
class FirstEntity {
...
/**
* @var \App\Entity\ThirdEntity
*
* @ORM\OneToOne(targetEntity="App\Entity\ThirdEntity")
*/
protected $thirdEntity;
class SecondEntity {
...
/**
* @var \App\Entity\ThirdEntity
*
* @ORM\OneToOne(targetEntity="App\Entity\ThirdEntity")
*/
protected $thirdEntity;
$thirdEntity
field cant be null.
Is there any way to return result by query builder or native query like array_diff() opertion:
$firsts = array_map(function (FirstEntity $firstEntity) {
return $firstEntity->getThirdEntity()->getId();
}, $this->em->getRepository(FirstEntity::class)->findAll());
$seconds = array_map(function (SecondEntity $secondEntity) {
return $secondEntity->getThirdEntity()->getId();
}, $this->em->getRepository(SecondEntity::class)->findAll());
return array_diff($firsts, $seconds);
So what I want is a list of all ThirdEntity
that is linked to a FirstEntity
but not to a SecondEntity
.
Upvotes: 0
Views: 55
Reputation: 1977
The most performant way to do this, is using a native query or the query builder (or multiple native queries/query buidlers). This way, the database will do all the filtering for you, meaning Doctrine doesn't have to do to much work.
The query builder is the easiest way, but does require you to also map from ThirdEntity
to FirstEntity
and SecondEntity
- the following code assumes you have that mapping in place.
$qb = $em->createQueryBuilder();
$result = $qb->select('t')->from('ThirdEntity', 't')
->innerJoin('t.firstEntity', 'f')
->leftJoin('t.secondEntity', 's')
->where($qb->expr()->isNull('s.id'));
->getQuery()->getResult();
What happens here, is that we ask the database to take all ThirdEntity
records, inner join
them with all FirstEntity
records (so a ThirdEntity
without FirstEntity
won't be included). Then we left join
that with SecondEntity
, which means that if the ThirdEntity
is also linked to a SecondEntity
its data becomes available for filtering, otherwise we get NULL
for all the SecondEntity
columns. The last step is to select only those records where there is no SecondEntity
(meaning its ID is null
).
Depening on the exact dataset, this "one query" approach may not give you the best performance. It could be faster to first select the ID's of all ThirdEntity
items that have a relation to a FirstEntity
and then (in a separate query, where you use that ID list as parameter) filter out those items that also have a relation to a SecondEntity
. It might also be faster to do those two things the other way around. I'm not expecting that though, so we'll leave that for another question (or another answer to this question).
Upvotes: 1