2016-06-29 19 views
1

habe ich eine Firma Klasse, die Benutzer verweist:Erhalten Array von referenzierten ids in Lehre ODM

/** 
* @MongoDB\Document() 
*/ 
class Company { 

    /* ... */ 

    /** 
    * @MongoDB\ReferenceMany(targetDocument="Topboard\UserBundle\Document\User", inversedBy="companies") 
    */ 
    protected $users; 
} 

In meinem Controller muss ich überprüfen, ob der Verweis auf den Benutzer im Unternehmen vorhanden ist, und halten nur den Verweis auf dieser Benutzer, nicht andere Referenzen. Ich möchte auch mehrere Datenbankanforderungen für Benutzer vermeiden. Ich möchte nur überprüfen, ob die ID der Referenzen $currentUserId entspricht.

public function getCompanyAction($companyId, $currentUserId) { 
    $dm = $this->get('doctrine_mongodb')->getManager(); 
    $company = $dm->getRepository('TopboardAppBundle:Company')->findOneById($companyId); 

    foreach ($company->getUsers() as $user) { 
     // Foreach will query each user separetly. This is not what I need. 
     // I need somehow access array of references' ids 
     // and compare them with the $currentUserId 
     if($user->getId() !== $currentUserId){ 
      // Remove reference 
     }   
    } 

    return $company; 

} 

Antwort

1

Nach Untersuchung stellte sich heraus, dass die Abfrage ausgelöst wird, wenn Sammlung initialisiert wird eine Abfrage pro Dokument später zu vermeiden (für die Argumentation, warum wir nicht noch besser this comment on GH sehen tun können). Der Fall ist allerdings nicht verloren, Lösung ist nicht in der Nähe ist schön, aber manchmal OD/RMs erfordert diese, wenn Leistung zuerst kommen muss:

$users = $company->getUsers(); 
// condition below assumes $company is loaded from db so $users is in fact instance of PersistentCollection(Interface) 
if ($users->isInitialized()) { 
    $ids = $users->map(function($user) { 
     return $user->getId(); 
    })->toArray(); 
} else { 
    $ids = array_map(function($dbRef) { 
     /* this depends on reference type */ 
     return (string) $dbRef['$id']; 
    }, $users->getMongoData()); 
} 

Sie könnten auch nur Ihre Logik an Orten, wo ich bin Mapping Sammlungen, um eine Liste von IDs referenzierter Benutzer zu erhalten.

Original-Antwort, die für einzelne Referenzen oder unitinitailzed Proxies

Wenn Objekt geladen wird noch nicht relevant ist (dh es ist immer noch nicht initialisierte Proxy) dann für dieses Dokument Kennung nicht gefragt, zusätzliche Abfragen auslösen wird, ist hier Schnipsel einer Proxy Klasse von ODM in meinem Projekt generiert:

public function getId() 
{ 
    if ($this->__isInitialized__ === false) { 
     return parent::getId(); 
    } 


    $this->__initializer__ && $this->__initializer__->__invoke($this, 'getId', []); 

    return parent::getId(); 
} 

auch erweitern ein wenig beantworten, können Sie n + 1 Problem mit priming, auf diese Weise ODM wird holen alle Refe verhindern Dokumente in einer Abfrage umbenannt.

+0

Proxy klingt ungefähr richtig. Also schlagen Sie vor, den ID-Getter in der User-Klasse zu ändern? Ich denke, das Problem ist, dass wenn ich 'foreach', es bereits eine DB-Anfrage auslöst. – Websirnik

+0

Nein, Ihr Getter sollte intakt bleiben, Sie können die automatisch generierte Proxy-Klasse überprüfen (sie befinden sich normalerweise in 'app/cache/lcl/doctrine/odm/mongodb/Proxies /'). Wie für 'foreach' sollte es keine Abfrage alleine auslösen, da Ihre Referenz die Besitzerseite ist, die somit nach dem ersten Holen bereits im Dokument verfügbar ist. – malarzm

+0

Was ich meine ist, ist Ihr Code sieht korrekt aus und sollte keine zusätzlichen Abfragen an dieser Stelle auslösen – malarzm