2013-05-05 2 views
0

Helo,Ленивый нагрузки между ссылочных документов по MongoDB с Doctrine ODM

во-первых, пожалуйста, простите мой английский, это не очень хорошо.

Я переношу контейнер данных приложения Symfony2 в MongoDB, перед этим он запускается с MySQL.

Я добавил DoctrineMongoDBBundle и «почти все» отлично работает.

У меня есть некоторые ссылки между документами, в которых я хотел бы сохранить шаблон «ленивой загрузки», предлагаемый ORM доктрины. Я прочитал официальную документацию по Doctrine ODM,

и некоторые примеры, которые объясняют, как создать отношения и определить документы, чтобы получить «ленивую нагрузку» поведение,

, но я не могу заставить его работать.

В моем случае, у меня есть два документа, «путешествие» и «заметка» с 1 на: N отношениях я хочу сохранить, что-то вроде этого:

<?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 ... 

} 
?> 

Когда я добавить заметку к путешествиям Я понимаю, что результат для проездного документа должен быть:

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

и нотного документ должен быть:

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

, но сейчас я только получаю ссылку в записке документ, в то время как ссылка не появляется в проездном документе, и когда я делаю запрос в проездных документов Доктрины не нагружают соответствующие нотные документы:

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

процесс я следовать, чтобы добавить примечание к поездке выглядит следующим образом:

<?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(); 
      } 
     } 
    } 
} 
?> 

любых идеи или предложения, чтобы получить метод $ путешествия-> getNotes() может автоматически получать ссылки заметок через «ленивую нагрузку».

Большое спасибо заранее за вклад,

Zacarias

ответ

2

То, что вы хотите достичь это делается путем простого удаления атрибута mappedBy в ReferenceOne в $travel собственности:

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

Таким образом, доктрина будет хранить идентификаторы Notes в массиве $nodes.


С «mappedBy» вместо, Учение не хранит идентификаторы Нот в $notes массиве, но вместо этого он будет делать запрос, как это извлечь фактические ноты:

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

Обратите внимание, что IMHO это предпочтительный подход, так как таким образом, когда вы добавляете/удаляете заметку, вам не нужно обновлять документ Travel. (Однако вам придется добавить индекс на поле $ путешествий)

заметить также, что с ReferenceMany, используя mappedBy лениво: только тогда, когда вы пытаетесь цикл $notes массива, то он будет на самом деле выполнить запрос, так это также легкий.

См. doc для получения дополнительной информации.

Смежные вопросы