I have a mongodb document in symfony2 with an embeded document:
/**
* @MongoDB\EmbedMany(targetDocument="Restriction")
*/
private $restrictions = array();
public function __construct()
{
$this->restrictions = new \Doctrine\Common\Collections\ArrayCollection();
}
The restriction document has two properties. from_pos and length. I want this array to be always sorted by from_pos, so in the whole application I will be always sure that this list is sorted.
Is there an easy way to do this automatically? I mean, to call addRestriction function and this will be automatically saved in the mongodb database sorted by the key I want.
Currently the addRestriction function just adds the new document to the end of the list.
/**
* Add restriction
*
* @param MyBundle\Document\Restriction $restriction
*/
public function addRestriction(\MyBundle\Document\Restriction $restriction)
{
$this->restrictions[] = $restriction;
}
I could update this function to insert the restriction into the desired position, but I would like to know if there is an easiest way.
The solution is to use custom collections.
This is the SortedCollection class I've developed. When adding an element just put it in the correct position and slice the other elements.
<?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;
}
}
And in the Document just set the SortedCollection class in the constructor.
<?php
class MyDocument
{
/**
* @MongoDB\EmbedMany(
* collectionClass="SortedCollection",
* targetDocument="...."
* )
*/
private $sorted_list = array();
public function __construct()
{
$this->sorted_list = new SortedCollection();
}
}