2013-05-05 7 views
0

Helo,charge Lazy entre documents référencés sur MongoDB avec Doctrine ODM

tout d'abord, s'il vous plaît excuser mon anglais, est pas très bon.

Je migre le conteneur de données d'une application Symfony2 vers MongoDB, avant de l'exécuter avec MySQL.

J'ai ajouté le DoctrineMongoDBBundle et "presque tout" fonctionne parfaitement.

J'ai quelques références entre des documents dans lesquels je voudrais garder le modèle de "charge paresseuse" offert par l'ORM Doctrine. J'ai lu la documentation officielle pour la doctrine ODM,

et quelques exemples qui expliquent comment créer des relations et de définir les documents pour obtenir un comportement "charge paresseux",

mais je ne peux pas le faire fonctionner.

Dans mon cas, j'ai deux documents, « voyage » et « note » avec un 1: relation N Je veux garder, quelque chose comme ceci:

<?php 

namespace MyApp\TravelBundle\Document; 

use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; 
use Doctrine\Common\Collections\ArrayCollection; 
use Symfony\Component\Validator\Constraints as Assert; 
use Gedmo\Mapping\Annotation as Gedmo; 

/** 
* Travel 
* 
* @ODM\Document(collection="travel") 
*/ 
class Travel { 

    /** 
    * @var \MyApp\NoteBundle\Document\Note 
    * 
    * @ODM\ReferenceMany(targetDocument="\MyApp\NoteBundle\Document\Note", mappedBy="travel", sort={"createdAt"="asc"}) 
    */ 
    private $notes; 

    // more properties ... 

    public function __construct() { 
     $this->notes = new \Doctrine\Common\Collections\ArrayCollection(); 
    } 

    /** 
    * Add notes 
    * 
    * @param \MyApp\NoteBundle\Document\Note $notes 
    */ 
    public function addNote(\MyApp\NoteBundle\Document\Note $notes) { 
     $this->notes[] = $notes; 
    } 

    /** 
    * Remove notes 
    * 
    * @param \MyApp\NoteBundle\Document\Note $notes 
    */ 
    public function removeNote(\MyApp\NoteBundle\Document\Note $notes) { 
     $this->notes->removeElement($notes); 
    } 

    /** 
    * Get notes 
    * 
    * @return Doctrine\Common\Collections\Collection $notes 
    */ 
    public function getNotes() { 
     return $this->notes; 
    } 

    // more methods ... 

} 
?> 

<?php 

namespace MyApp\NoteBundle\Document; 

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

/** 
* Note 
* 
* @ODM\Document(collection="note") 
*/ 
class Note 
{ 
    /** 
    * @var \MyApp\TravelBundle\Document\Travel 
    * 
    * @ODM\ReferenceOne(targetDocument="MyApp\TravelBundle\Document\Travel", inversedBy="notes") 
    */ 
    private $travel; 

    // more properties ... 

    /** 
    * Set travel 
    * 
    * @param \MyApp\TravelBundle\Document\Travel $travel 
    * @return Note 
    */ 
    public function setTravel(\MyApp\TravelBundle\Document\Travel $travel) { 
     $this->travel = $travel; 
     $travel->addNote($this); 

     return $this; 
    } 

    // more methods ... 

} 
?> 

Quand j'ajoute une note à un Voyage Je comprends que le résultat du document de Voyage doit être:

{ "_id" : ObjectId("5183aa63095a1a3921000000"), 
    "name" : "First travel", 
    "isActive" : true, 
    "createdAt" : Date(1367583331000), 
    "updatedAt" : Date(1367583331000), 
    "notes" : [{ "$ref" : "note", 
    "$id" : ObjectId("5183aa63095a1a3955000000"), 
    "$db" : "mydb" }] 
} 

et pour le document de note doit être:

{ "_id" : ObjectId("5183aa63095a1a3955000000"), 
    "travel" : { "$ref" : "travel", 
    "$id" : ObjectId("5183aa63095a1a3921000000"), 
    "$db" : "mydb" }, 
    "note" : "First note", 
    "createdAt" : Date(1367583331000), 
    "updatedAt" : Date(1367583331000) } 

mais pour l'instant je reçois seulement une référence dans le document de noter que même si aucune référence apparaît dans le document de Voyage, et quand je fais une requête dans la doctrine de document de Voyage ne pas charger les documents de notes connexes:

<?php 
. 
. 
$travel = $dm->getRepository('TravelBundle:Travel')->findCurrentTravel($user->getId()); 
$travel->getNotes(); // IS EMPTY :(
. 
. 
?> 

Le processus Je suis d'ajouter une note à un Voyage est la suivante:

<?php 

namespace MyApp\TravelBundle\Controller; 

use Symfony\Bundle\FrameworkBundle\Controller\Controller; 
use Symfony\Component\HttpFoundation\Request; 
class TravelController extends Controller { 

    public function createNoteAction(Request $request) { 
     $dm = $this->get('doctrine.odm.mongodb.document_manager'); 
     $travel = $dm->getRepository('TravelBundle:Travel')->findCurrentTravel($user->getId()); 
     $entity = new Note(); 
     $form = $this->createForm(newNoteType(), $entity); 
     if ($request->isMethod('POST')) { 
      $form->bind($request); 
      if ($form->isValid()) { 
       $entity->setTravel($travel); 
       $dm>persist($travel); 
       $dm>persist($entity); 
       $dm>flush(); 
      } 
     } 
    } 
} 
?> 

Toutes les idées ou suggestions pour la méthode de Transport- $> getNotes() peut récupérer automatiquement les notes référencées par la « charge paresseux ».

Merci beaucoup d'avance pour les contributions,

Zacarías

Répondre

2

Qu'est-ce que vous voulez réaliser est fait en enlevant simplement l'attribut mappedBy dans le ReferenceOne de la propriété $travel:

@ODM\ReferenceMany(targetDocument="\MyApp\NoteBundle\Document\Note", sort={"createdAt"="asc"}) 

De cette manière, la doctrine stockera les ID Notes dans le tableau $nodes.


Avec « mappedBy » à la place, la doctrine ne stocke pas les ID des billets dans le tableau $notes, mais il fera une requête comme celui-ci pour récupérer les notes réelles:

db.Notes.find({travel.$id: <travelId>}); 

Notez que, à mon avis, celui-ci est l'approche préférée, puisque de cette façon, lorsque vous ajoutez/supprimez une note, vous n'avez pas besoin de mettre à jour le document de voyage. (Mais vous devrez ajouter un index sur le champ Voyage de $)

Notez également que, avec ReferenceMany, en utilisant le mappedBy est paresseux: que lorsque vous essayez de cycle, le tableau $notes il exécute en fait la requête, il est également léger. Pour plus d'informations, consultez le doc.

Questions connexes