Search code examples
mongodbsymfonydoctrine-ormdoctrine-odmodm

Persisting a document suddenly stops returning next identifier value (ALNUM strategry)


I have Symfony 2.6 application and using doctrine-odm-bundle 3.0.2 (doctrine-odm: 1.1.2, mongodb: 1.4.0).

My document has referenceMany and referenceOne in attributes and when I create new instance of it, fill fields and persist - it goes fine in the begining. I can create few nearly empty documents, with referenced document(s) or without and it works fine. At some point I am trying to add new item in the database and getting an error:

E11000 duplicate key error collection: test.Product index: _id_ dup key: { : 0 }

The message is clear - I can see that there was a document added to the collection with id = 0, therefore second one can't go -> duplicate entry. But why it suddenly starts to return "0" for id? Even though, I checked doctrine_increment_ids collection - counter for id is being incremented. But $product->getId() becomes "0" after persist.

If I drop the database and start all over - it works, I can still add new products in the collection. Let's say I successfully created 12 products. Creating 13th resulting a document with id=0 being persisted in the collection. 14th fails with duplicate error.

Can you please help to troubleshoot or suggest an idea where does it go wrong?

P.S> I am not considering an upgrade of Symfony2 (at this point) neither as doctrine-odm-bundle (it depends on newer Symfony2 as well) - migration efforts are quite high and I am not sure it will fix the issue. First I want to find out the root cause.

// Document Product

/**
 * @MongoDB\Document
 * @MongoDB\HasLifecycleCallbacks
*/
class Product
{
    /** @MongoDB\Id(strategy="ALNUM", type="int") */
    protected $id;

    /**
     * @Gedmo\ReferenceOne(type="entity", class="Entity\User", inversedBy="products", identifier="userId")
     */
    protected $user;

    /**
     * @MongoDB\Field(name="user_id", type="int")
     */
    protected $userId;

    /**
     * @MongoDB\ReferenceMany(
     *     targetDocument="Picture",
     *     discriminatorMap={"file" = "File", "picture" = "Picture"},
     *     discriminatorField="discr",
     *     defaultDiscriminatorValue="picture"
     * )
     * @Assert\Valid
     */
    protected $pictures;

    ...
}

// Entity User

/**
 * User entity
 * @ORM\Entity
 * @ORM\Table(name="users")
 */
class User
{

    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @var ArrayCollection $textures
     * 
     * @Gedmo\ReferenceMany(type="document", class="Document\Product", mappedBy="user")
     */
    protected $products;
    ...
}

// Document Picture

/**
 *  @MongoDB\Document
 *  @MongoDB\InheritanceType("SINGLE_COLLECTION")
 *  @MongoDB\DiscriminatorField("discr")
 *  @MongoDB\DiscriminatorMap({"file" = "File", "picture" = "Picture"})
 * @MongoDB\DefaultDiscriminatorValue("picture")
 * @MongoDB\HasLifecycleCallbacks
 */
class Picture
{

    /**
     * 
     * @MongoDB\Id(strategy="ALNUM", type="int")
     */
    protected $id;

    /**
     * @MongoDB\ReferenceOne(targetDocument="Product")
     *
     * @var Product $product
     */
    protected $product;
    ...
 }

Solution

  • Documentation reading always helps (generation strategies). Basically, strategy="ALNUM" and type="int" just can't go together :)

    Change strategy to INCREMENT and remove type="int" if you want to have integers in your _id. Or you can change type to string to continue with _id being an alphanumeric string.