2013-04-19 2 views
1

Я играю с UniqueIndex, который я выбрал из документа Doctrine ODM, и, похоже, у меня есть misanderstood того, что он намерен делать.Doctrine Mongo ODM UniqueIndex реплицируется

Действительно у меня есть ключевые слова документа, преобразованный Doctrine ODM:

Namespace App\Document; 

use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; 

/** 
* @ODM\Document 
* @ODM\UniqueIndex(keys={"name"="asc", "lang"="asc"}) 
*/ 
class Keyword { 

    /** @ODM\Id(strategy="AUTO") */ 
    protected $id; 

    /** @ODM\String */ 
    protected $name; 

    /** @ODM\String */ 
    protected $lang; 

    .... 

Как вы можете видеть, что документ имеет uniqueIndex на 2 ключа (имя и Lang)

У меня есть все простой скрипт, который упорствовать этот документ

.... 
    .... 
    $keyword=new \App\Document\Keyword(); 
    $keyword->setCreateDate(new \DateTime()); 
    $keyword->setLang("fr"); 
    $keyword->setLastParseDate(new \DateTime()); 
    $keyword->setName("test"); 

    $dm->persist($keyword); 

    $dm->flush(); 

Теперь, когда я нашел из Монго оболочки, мои данные с одной и той же пары Имя/Ланг реплицируются, когда они должны быть уникальными:

> db.Keyword.find() 
{ "_id" : ObjectId("5171c72c6155795e47000000"), "name" : "test", "lang" : "fr", "createDate" : ISODate("2013-04-19T22:37:32Z"), "lastParseDate" : ISODate("2013-04-19T22:37:32Z") } 
{ "_id" : ObjectId("5171c7366155796147000000"), "name" : "test", "lang" : "fr", "createDate" : ISODate("2013-04-19T22:37:42Z"), "lastParseDate" : ISODate("2013-04-19T22:37:42Z") } 
{ "_id" : ObjectId("5171c7406155796447000000"), "name" : "test", "lang" : "fo", "createDate" : ISODate("2013-04-19T22:37:52Z"), "lastParseDate" : ISODate("2013-04-19T22:37:52Z") } 
{ "_id" : ObjectId("5171c7fd615579a747000000"), "name" : "test", "lang" : "fo", "createDate" : ISODate("2013-04-19T22:41:01Z"), "lastParseDate" : ISODate("2013-04-19T22:41:01Z") } 
{ "_id" : ObjectId("5171c7fe615579aa47000000"), "name" : "test", "lang" : "fo", "createDate" : ISODate("2013-04-19T22:41:02Z"), "lastParseDate" : ISODate("2013-04-19T22:41:02Z") } 

Моя цель - сделать парное имя/язык уникальным для настойчивости.

Так что я, наконец, есть два вопроса:

  • Что UniqueIndex сделан для? (Потому что он не предотвращает репликацию)
  • Должен ли я использовать custom strategy, который объединяет имя и Lang как уникальный идентификатор? Это обычное использование?

EDIT:

Благодаря @gview советы, которые я нашел, что я не ensureIndexes. Я исправил эту ссылку: http://www.testically.org/2011/08/25/using-a-unique-index-in-mongodb-with-doctrine-odm-and-symfony2/

Но вместо того, чтобы обновлять мою запись, она выдает ошибку для дублирования записи. Должен ли я использовать пользовательский идентификатор, как я сказал выше?

+0

Вы уверены, что индекс действительно существует в коллекции? Вы запустили доктрину php app/console: mongodb: schema: создать задачу? – gview

+0

Нет, я этого не знаю. Но, похоже, это что-то использовать в приложении Symfony, не так ли? потому что на самом деле я не использую symfony! Я просто работаю над небольшим сценарием из любой структуры. –

+0

Я нашел несколько документов по адресу: http://www.testically.org/2011/08/25/using-a-unique-index-in-mongodb-with- doctrine-odm-and-symfony2/ –

ответ

0

Индекс гарантирует, что документы не будут дублированы.

Если вы хотите, чтобы сделать эквивалент "REPLACE INTO", вы должны либо:


Получить документ, если нет, то установите значение:

$keyword= $dm->findBy(array("name"=> $name, "lang"=> $lang)); 
if(!$keyword) { 
    $keyword= new Keyword(); 
    $dm->persist($keyword); 
} 
$keyword->setCreateDate(new \DateTime()); 
$keyword->setLang("fr"); 
$keyword->setLastParseDate(new \DateTime()); 
$keyword->setName("test"); 

Это приведет к 2 запросам.


Или:

Делают upsert:

$dm->createQueryBuilder('Keyword') 
    ->setNewObj(array(
     'lang' => 'fr', 
     'name' => 'test', 
     // ... other fields 
    )) 
    ->field('lang')->equals('fr') 
    ->field('name')->equals('test') 
    ->getQuery() 
    ->execute(); 

Это будет обновлять документ, если присутствует, в противном случае он будет создавать новый документ.

Однако новый документ создан из необработанного массива , фактически минуя все события Doctrine (например, аннотация @Timestampeble).

Так что если дополнительный запрос не является проблемой, используйте первый метод.

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