2016-05-26 4 views
0

У меня есть документ MongoDB в Symfony2 с документом поместить его:доктрина Embeded документ поддержания порядка с помощью ключа

/** 
* @MongoDB\EmbedMany(targetDocument="Restriction") 
*/ 
private $restrictions = array(); 

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

В этом документе ограничение имеет два свойства. from_pos и length. Я хочу, чтобы этот массив всегда сортировался by_pos, поэтому во всем приложении я всегда буду уверен, что этот список отсортирован.

Есть ли простой способ сделать это автоматически? Я имею в виду, чтобы вызвать функцию addRestriction, и это будет автоматически сохранено в базе данных mongodb, отсортированной по ключевому элементу, который я хочу.

В настоящее время функция addRestriction просто добавляет новый документ в конец списка.

/** 
* Add restriction 
* 
* @param MyBundle\Document\Restriction $restriction 
*/ 
public function addRestriction(\MyBundle\Document\Restriction $restriction) 
{ 
    $this->restrictions[] = $restriction; 
} 

Я мог бы обновить эту функцию, чтобы вставить ограничение в нужное положение, но я хотел бы знать, если есть простой способ.

ответ

0

Решение состоит в использовании пользовательских коллекций.

http://docs.doctrine-project.org/projects/doctrine-mongodb-odm/en/latest/reference/custom-collections.html

Это класс SortedCollection я разработал. При добавлении элемента просто поместите его в правильное положение и срезайте другие элементы.

<?php 

use Doctrine\Common\Collections\ArrayCollection; 

/** 
* Array collection with elements alwais in order 
*/ 
class SortedCollection extends ArrayCollection{ 

    /** 
    * Interrnal flag to avoid recursive call to reindex function while reindexing 
    * @var boolean 
    */ 
    protected $reindexing = false; 

    public function add($value){ 
     $it = $this->getIterator(); 
     while($it->valid() && $it->current()->compareTo($value) < 0){ 
      $it->next(); 
     } 

     // slice elements 
     $prev = $value; 
     while ($it->valid()){ 
      // Save current element 
      $aux = $it->current(); 

      // Add previous element 
      $this->offsetSet($it->key(), $prev); 

      // Set previous element to current for next iteration 
      $prev = $aux; 
      $it->next(); 
     } 

     // Add final element 
     parent::add($prev); 

     return true; 
    } 
} 

И в документе просто задайте класс SortedCollection в конструкторе.

<?php 

class MyDocument 
{ 
    /** 
    * @MongoDB\EmbedMany(
    *  collectionClass="SortedCollection", 
    *  targetDocument="...." 
    *) 
    */ 
    private $sorted_list = array(); 

    public function __construct() 
    { 
     $this->sorted_list = new SortedCollection(); 
    } 
}