简体   繁体   中英

Doctrine / DQL get the entities having the exactly the same related entities

Imagine i have a entity Person which has a many-to-many relation with Vehicle

How can i find another Person exactly having the same Vehicles?

Example:

Person 1 (ID=1) has vehicle with id 5,6 and 7

Person 2 (ID=2) has vehicles with id 5,6,8 -> should not match with person 1!

Person 3 (ID=3) has vehicle with id 5 ->should not match with person 1!

Person 4 (ID=4) has vehicles with id 5,6 and 7 -> should match with person 1

Person 5 (ID=5) has vehicles with id 5,6 and 7 -> should match with person 1 and person 4

So what is the DQL expression for that?

I tried already with "IN" but this will also match even if just one of my id's match.

Thanks

Clean DQL :

$query = $entityManager->createQuery("
  SELECT p, pv 
    FROM Person p
    INNER JOIN p.vehicles pv 
    WHERE pv.id in (
      SELECT v.id
        FROM Vehicle v
        INNER JOIN v.persons vp
        WHERE p.id <> vp.id
    ) GROUP BY p.id
    HAVING count(pv.id) > 1");
$persons = $query->getResult();

Explanation : To get persons with same vehicles, you need to get vehicles, that equal to person's, but attached to other. HAVING regulates count of minimal same vehicles, by which we group persons in collection.

You can use more flexible approach with PHP , that get only persons with full identical vehicles. Steps:

  1. get all persons with vehicles
  2. compare vehicles Ids
  3. add to result only persons IDs with the same vehicles
  4. get collection of persons with same vehicles

Code :

<?php

$query = $entityManager->createQuery("select p,v from Person p JOIN p.vehicles v");
$persons = $query->getArrayResult();

$personsIdsWithSameVehicles = [];

foreach ($persons as $person) {
    $vehiclesIds = array_column($person['vehicles'], 'id');
    $subPersons = array_filter($persons, function($filterPerson) use ($person) {
       if($filterPerson['id'] != $person['id']) return $filterPerson;
    });

    foreach ($subPersons as $subPerson) {
        $subVehiclesIds = array_column($subPerson['vehicles'], 'id');
        if(count($vehiclesIds) == count($subVehiclesIds) and
            empty(array_diff($vehiclesIds, $subVehiclesIds))) {

            $personsIdsWithSameVehicles[] = $person['id'];
            break;

        }
    }
}

$personsQuery = $entityManager->createQuery("select p from Person p where p.id IN(:persons)");
$personsQuery->setParameter('persons', $personsIdsWithSameVehicles);
$personsWithSameVehicles = $personsQuery->getResult();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM