Git Product home page Git Product logo

couchdb-odm's Introduction

CouchDB ODM

Build Status Scrutinizer Quality Score

Doctrine CouchDB is a mapper between PHP and CouchDB documents. It uses a metadata mapping pattern to map the documents to plain old php objects, no ActiveRecord pattern or base class of any kind is necessary.

Metadata mapping can be done through annotations, xml, yaml or php. A sample PHP object that is mapped to CouchDB with annotations looks like this:

/**
 * @Document
 */
class Article
{
    /** @Id */
    private $id;

    /**
     * @Field(type="string")
     */
    private $topic;

    /**
     * @Field(type="string")
     */
    private $text;

    /**
     * @ReferenceOne(targetDocument="User")
     */
    private $author;

    // a bunch of setters and getters
}

A simple workflow with this document looks like:

<?php
$article = new Article();
$article->setTopic("Doctrine CouchDB");
$article->setText("Documentation");
$article->setAuthor(new Author("beberlei"));

// creating the document
$dm->persist($article);
$dm->flush();

$article = $dm->find("Article", 1234);
$article->setText("Documentation, and more documentation!");

// update the document
$dm->flush();

// removing the document
$dm->remove($article);
$dm->flush();

You can play around with the sandbox shipped in the sandbox/ folder of every git checkout or read the documentation at https://www.doctrine-project.org/projects/doctrine-couchdb-odm/en/latest/index.html

couchdb-odm's People

Contributors

bartfaitamas avatar beberlei avatar carusogabriel avatar dbu avatar dragoonis avatar fdomig avatar guilhermeblanco avatar hami9x avatar hlubek avatar igorw avatar j13k avatar janpieper avatar jwage avatar kevinyien avatar kore avatar lsmith77 avatar lucifurious avatar marnusw avatar mehrdadmhd avatar mikesimonson avatar naderman avatar ngroot avatar ocramius avatar patromo avatar powerhamster avatar saem avatar schaumiii avatar taion809 avatar tobmaster avatar tobys avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

couchdb-odm's Issues

Null _rev passed to CouchDB

We tried mapping the CouchDB _rev string to a PHP property. The line we used in the XML mapping file was:

<field name="etag" type="string" version="true" json-name="_rev"></field>

This works when fetching a document from the database, but it fails when trying to persist a new document to the database.

The problem is in Doctrine\ODM\CouchDB\UnitOfWork::flush() where the field values are converted to JSON values. The _rev version field is included in the JSON, even if it is null. This results in a 400 bad request response from CouchDB.

Our workaround is to replace line 1072 with the following code snippet:

$jsonName = $class->fieldMappings[$fieldName]['jsonName'];
if( $jsonName != '_rev' || $fieldValue ) $data[$jsonName] = $fieldValue;

Rather than testing the JSON name, it might be more consistent with the rest of your design to test $class->fieldMappings[$fieldName]['isVersionField'] or to check whether $fieldName is equal to $class->versionField.

ID generator strategy not inherited from parent class

Hi,

We encountered difficulties with class inheritance when using an assigned ID strategy. This is because, when field mappings are copied from a parent class to a child, the name of the ID field is copied, but the ID generator strategy is not.

Steps to reproduce:

  1. Create a parent class and a child class that inherits from it. Put the ID field in the parent class.
  2. Define the mapping with an assigned ID strategy.
  3. Instantiate a new child object, assign an ID and try to persist it to the database.

The exception "Detached document passed to persist()" is thrown from line 349 of UnitOfWork. The default ID generator strategy is "UUID", so UnitOfWork incorrectly assumes that the document is detached because the ID field is populated.

We have also discovered that the isVersioned and versionField properties are not copied from parent to child.

Our workaround is to add lines to Doctrine\ODM\CouchDB\Mapping\ClassMetaDataFactory::addFieldMapping() as follows:

    private function addFieldMapping(ClassMetadataInterface $class, ClassMetadataInterface $parent)
    {
        foreach ($parent->reflFields as $name => $field) {
            $class->reflFields[$name] = $field;
        }

        foreach ($parent->fieldMappings as $name => $field) {
            $class->fieldMappings[$name] = $field;
        }

        foreach ($parent->jsonNames as $name => $field) {
            $class->jsonNames[$name] = $field;
        }

        if ($parent->identifier) {
            $class->setIdentifier($parent->identifier);
            $class->idGenerator = $parent->idGenerator;  // <----- added line
        }

        // Added lines from here...
        if ($parent->isVersioned) {
            $class->isVersioned = $parent->isVersioned;
            $class->versionField = $parent->versionField;
        }
        // ... to here
    }

So far this change hasn't broken anything else for us.

Callback for failure on document persist

When documents are persisted, having the ability to specify a callback that is called on failure to persist a particular document would be immensely helpful.

This would allow developers to manage the conflicts automatically using code; or by providing users feedback of the conflict and letting them manage it.

I propose something like the following:

$documentManager->persist($document, function($error)
{
    // Error management logic
});

If this were implemented as an optional parameter this would remain compatible with code using the existing api.

My question is: Were I to implement this feature and send a PR, would it be accepted?

cannot EmbedOne a Document with ReferenceOne or ReferenceMany properties in it

Hi all. Im new in programming and couchdb-odm. I have the following problem:

I have a Document A in which I'm trying to embedOne another Document B which is already existing in my Database, and which has some ReferenceOne and ReferenceMany properties pointing at some Documents C and D respectively.

I get an error: Undefined index: parent in /vendor/doctrine/couchdb-odm/lib/Doctrine/ODM/CouchDB/Mapping/EmbeddedDocumentSerializer.php on line 84

Am I doing something wrong? Thanks in advance.

Tagging

Hey guys, commit 610b900 broke my CouchDB ODM implementation for Flow. This is btw nothing you guys have to fix, but while debugging I wondered if you could start tagging new alpha versions in this package.

The last tag (alpha2) does not yet have a composer manifest, so if you use composer you're now forced to stick to master or a specific commit.

The ODM should the common proxy interface

This would make it compatible with libraries handling this proxy (for instance JMSSerializerBundle has some logic to handle doctrine proxies but won't catch the CouchDB ones currently) and will allow you to use Doctrine\Common\Debug::dump()

PHP 5.6 compability

This patch should be ported to make the CouchDB ODM compatible with PHP 5.6 doctrine/orm@4b504c9

This is especially important using the CouchDB-ODM-SF2-Bundle with the FOSUserBundle in PHP 5.6.

Set "type" for document

Bundle saves and searches documents with the type field which equals to the document class name, for example "Acme.DemoBundle.CouchDocument.Settings".

Is there any way to set custom "type", for example:

/**
* @CouchDB\Document(type="Settings")
*/
class Settings
{
  /**
   * @CouchDB\Id
   */
  protected $id;
}

Format of DateTime types

When a datetime type is stored in couch, a conversion is made. The used format "Y-m-d H:i:s.u" is both adverse and hard coded.

First, it should be adjustable without changing Doctrine code. Second, why not take a format which is parseable by Spidermonkey like "r" as default?

providing invalid credentials ends in an infinite loop

There is no handling for invalid credentials in Doctrine\CouchDB\HTTP\SocketClient.php so it ends in an infinite loop.

  #    Time      Memory      Function                                                      Location
-----------------------------------------------------------------------------------------------------------------------
  1    0.0007      650752    {main}( )                                                     ../app_dev.php:0
  2    0.0259     5910352    Symfony\Component\HttpKernel\Kernel->handle( )                ../app_dev.php:24
  3    0.0450     8872896    Symfony\Bundle\FrameworkBundle\HttpKernel->handle( )          ../bootstrap.php.cache:547
  4    0.0451     8873904    Symfony\Component\HttpKernel\HttpKernel->handle( )            ../classes.php:5013
  5    0.0451     8873904    Symfony\Component\HttpKernel\HttpKernel->handleRaw( )         ../classes.php:4040
  6    0.0698    12040336    call_user_func_array ( )                                      ../classes.php:4070
  7    0.0698    12040704    My\DummyBundle\Controller\IndexController->indexAction( )     ../classes.php:4070
  8    0.0757    13437232    Doctrine\ODM\CouchDB\DocumentManager->persist( )              ../IndexController.php:87
  9    0.0757    13437232    Doctrine\ODM\CouchDB\UnitOfWork->scheduleInsert( )            ../DocumentManager.php:257
 10    0.0757    13437544    Doctrine\ODM\CouchDB\UnitOfWork->doScheduleInsert( )          ../UnitOfWork.php:301
 11    0.0823    13901792    Doctrine\ODM\CouchDB\UnitOfWork->persistNew( )                ../UnitOfWork.php:317
 12    0.0825    13928200    Doctrine\ODM\CouchDB\Id\CouchUUIDGenerator->generate( )       ../UnitOfWork.php:965
 13    0.0825    13928200    Doctrine\CouchDB\CouchDBClient->getUuids( )                   ../CouchUUIDGenerator.php:41
 14    0.0825    13928568    Doctrine\CouchDB\HTTP\LoggingClient->request( )               ../CouchDBClient.php:129
 15    0.0826    13928808    Doctrine\CouchDB\HTTP\SocketClient->request( )                ../LoggingClient.php:65
 16    0.0858    13942904    Doctrine\CouchDB\HTTP\SocketClient->request( )                ../SocketClient.php:249
 17    0.0883    13948056    Doctrine\CouchDB\HTTP\SocketClient->request( )                ../SocketClient.php:249
 18    0.0916    13953208    Doctrine\CouchDB\HTTP\SocketClient->request( )                ../SocketClient.php:249
 19    0.0963    13958384    Doctrine\CouchDB\HTTP\SocketClient->request( )                ../SocketClient.php:249
 20    0.1003    13963536    Doctrine\CouchDB\HTTP\SocketClient->request( )                ../SocketClient.php:249
...
295    0.9438    16428080    Doctrine\CouchDB\HTTP\SocketClient->request( )                ../SocketClient.php:249
296    0.9458    16433232    Doctrine\CouchDB\HTTP\SocketClient->request( )                ../SocketClient.php:249
297    0.9477    16438384    Doctrine\CouchDB\HTTP\SocketClient->request( )                ../SocketClient.php:249
298    0.9497    16443536    Doctrine\CouchDB\HTTP\SocketClient->request( )                ../SocketClient.php:249
299    0.9497    16443536    Doctrine\CouchDB\HTTP\SocketClient->buildRequest( )           ../SocketClient.php:133

The $body variable contains the following JSON:

{"error":"unauthorized","reason":"Name or password is incorrect."}

Question: assigned ID is not tested for NULL before update.

While processing a big data set and pushing information to various document types a single document did not hold an Id (NULL) and crashed the bulk update operation ('bad_request Document id must be string' exception).

Certainly it was my fault for not testing the assigned document id.
But I totally expected that the type of a 'required' field would be tested.

Is this something the documentation should mention?
May it be appropriate to test data types for 'required' fields automatically?
(if there is such a concept).

Why rely on a doctrine_metadata key in the Document?

I'm puzzled by the requirement for a doctrine_metadata key inside the CouchDB Document for the views to work.

I understand it being necessary for using associations. But what is the indexed key for, and why do the views not simply return a list of documents, regardless of them being "indexed" (whatever that means in this context) or not.

Why can't we just use the _design/doctrine_repositories/views/equal_constraint (or type_constraint) to do our basic querying? I'm not in favor of having vendor specific data inside my documents unless this is really helpful (as with the associations). If I have to migrate all my data simply to put doctrine_metadata.indexed: true in order to see it, it's a bit disappointing (unless, again, there's some clear logic I'm just not seeing yet).

Queries building problem with complex keys using last version of doctrine/couchdb-client.

Created issue in doctrine/couchdb-client project: doctrine/couchdb-client#5
Sorry, reposted there.

In case of any query building process like:
$query = $this->dm->createQuery('doctrine_repositories', 'equal_constraint')
->setKey(array($this->documentType, $field, $value))
->setIncludeDocs(true)
->toArray(true);

(DocumentRepository.php)

With setKey parameter as complex key in array format, result query will be generated with "keys=" parameter (please check commit doctrine/couchdb-client@18f1d30) instead of "key=". And as result 0 result will be returned.

Issue with missed interface, PHPDriver and Chain loader.

Hello.

After next commit - 593b6fc

I found a lot of major issues:

  1. Driver interface was removed but still used in DriverChain.php.
  2. PHPDriver implementation was removed. This one impacts old-style metadata loading with static loadMetadata method from the entity class. So, now couchdb-odm does't support metadata loading without annotations out of the box.
    3.(due to logic provided with this commit) Doctrine\ODM\CouchDB\Mapping\ClassMetadata usage should be replaced with (Doctrine\Common\Persistence\Mapping\ClassMetadata) thru all code.
  3. Also, this commit impacts integration with doctrine/couchdb-bundle integration (as result of implementation removing loadMetadataForClass(->Doctrine\Common\Persistence\Mapping\Driver\DefaultFileLocator->findMappingFile) is incompatible with for example couchdb-bundle style of entity-mapping)

So, after this commit couchdb-odm package seems to be absolutely broken if application uses couchdb-client + couchdb-odm + couchdb-bundle components and not use annotations for metadata.

In my fork i already patch it, so you can check it before fixing.
Hope it helps.

Thanks for you work,

Database compaction does not send correct Content-Type header

When calling compactDatabase on CouchDBClient the created request does not contain the needed header field Content-Type which causes an error from CouchDB.

Since there are no request to CouchDB which do not accept application/json as response this patch should easily fix it.

diff --git a/application/library/Doctrine/CouchDB/HTTP/SocketClient.php b/application/library/Doctrine/CouchDB/HTTP/SocketClient.php
index ee4402e..406c3a3 100644
--- a/application/library/Doctrine/CouchDB/HTTP/SocketClient.php
+++ b/application/library/Doctrine/CouchDB/HTTP/SocketClient.php
@@ -93,12 +93,13 @@ class SocketClient extends AbstractHTTPClient
     // available in the locale net.
     $request .= "Connection: " . ( $this->options['keep-alive'] ? 'Keep-Alive' : 'Close' ) . "\r\n";

+               $request .= "Content-type: application/json\r\n";
+
     // Also add headers and request body if data should be sent to the
     // server. Otherwise just add the closing mark for the header section
     // of the request.
     if ( $data !== null )
     {
-            $request .= "Content-type: application/json\r\n";
         $request .= "Content-Length: " . strlen( $data ) . "\r\n\r\n";
         $request .= "$data";
     }

Argument 1 passed to migrate() must be of the type array, null given

Hi,

I am getting the following error when calling findOneBy() and the document is found (it happens with some documents):

PHP Catchable fatal error: Argument 1 passed to Doctrine\ODM\CouchDB\Migrations\NullMigration::migrate() must be of the type array, null given, called in /vendor/doctrine/couchdb-odm/lib/Doctrine/ODM/CouchDB/UnitOfWork.php on line 168 and defined in /vendor/doctrine/couchdb-odm/lib/Doctrine/ODM/CouchDB/Migrations/NullMigration.php on line 30

Stack trace:

PHP 9. Doctrine\ODM\CouchDB\DocumentRepository->findOneBy() /src/Acme/MyBundle/AcmeMyBundle.php:1532

PHP 10. Doctrine\ODM\CouchDB\DocumentRepository->findBy() /vendor/doctrine/couchdb-odm/lib/Doctrine/ODM/CouchDB/DocumentRepository.php:171

PHP 11. Doctrine\ODM\CouchDB\View\ODMQuery->execute() /vendor/doctrine/couchdb-odm/lib/Doctrine/ODM/CouchDB/DocumentRepository.php:145

PHP 12. Doctrine\ODM\CouchDB\UnitOfWork->createDocument() /vendor/doctrine/couchdb-odm/lib/Doctrine/ODM/CouchDB/View/ODMQuery.php:47

PHP 13. Doctrine\ODM\CouchDB\Migrations\NullMigration->migrate() /vendor/doctrine/couchdb-odm/lib/Doctrine/ODM/CouchDB/UnitOfWork.php:168

DocumentRepository::findBy(array('id' => '')) returns empty result

The findBy method of class Doctrine\ODM\CouchDB\DocumentRepository returns an empty result while searching for criteria id.

$documentManager = $this->container
->get('doctrine_couchdb.odm.default_document_manager');

$repository = $documentManager
->getRepository('ACME\FooBundle\CouchDocument\User');

var_dump(
  $repository->find('9142249159baef526ebd78c088009861')
);
// returns expected result

var_dump(
  $repository->findBy(
    array('id' => '9142249159baef526ebd78c088009861')
  )
);
// returns an empty array

// tested with CouchDB 1.4.0

Feature: Make the CouchDB document type be custom

Now the CouchDB document type is generate from the PHP class name.
It would be useful to make the CouchDB document type be custom in the metadata,
may be like below:

@Document(type="customType")
*/
class MyPersistentClass
{
    /** @Id */
    private $id;
}

Proxy class instance cannot be bulk updated (missing _rev)

When loading a document which references another document a proxy class instance is used.
When this is bulk updated the update fails since there is no _rev field. I did not check but a normal update would probably fail as well.

When the proxy class loads the data from the database there is already an entry for the revision id in the document manager. This one need to be updated.

--- a/application/library/Doctrine/ODM/CouchDB/UnitOfWork.php
+++ b/application/library/Doctrine/ODM/CouchDB/UnitOfWork.php
@@ -221,6 +221,7 @@ class UnitOfWork
             if ( ($document instanceof Proxy && !$document->__isInitialized__) || isset($hints['refresh'])) {
                 $overrideLocalValues = true;
                 $oid = spl_object_hash($document);
+                               $this->documentRevisions[$oid] = $rev;
             }
         } else {
             $document = $class->newInstance();

setDirty() not available for all $managedCol in UnitOfWork::doMerge().

Fatal error: Call to undefined method Doctrine\ODM\CouchDB\PersistentIdsCollection::setDirty() in /lib/Doctrine/ODM/CouchDB/UnitOfWork.php on line 568

Tried to persist a @ReferenceMany(cascade="persist") which resulted in funny error messages.

Data given was an array of valid documents.

Did not test for further detail yet.

AnnotationException ::semanticalError() when getting class metadata

In the course of executing FormBuilder::getForm() on a document, I receive the following error as an AnnotationException:

The class "Yitznewton\DocmasterBundle\Document\Document" is not annotated with @annotation. Are you sure this class can be used as annotation? If so, then you need to add @annotation to the class doc comment of "Yitznewton\DocmasterBundle\Document\Document". If it is indeed no annotation, then you need to add @IgnoreAnnotation("Document") to the class doc comment of class Yitznewton\DocmasterBundle\Document\Document.

My class:

namespace Yitznewton\DocmasterBundle\Document;

/** @Document */
class Document
{
    /** @Id */
    protected $id;

    /** @Field(type="string") */
    protected $title;

    public function setTitle($v)
    {
      $this->title = $v;
    }
}

trace:

at AnnotationException ::semanticalError ('The class "Yitznewton\DocmasterBundle\Document\Document" is not annotated with @Annotation. Are you sure this class can be used as annotation? If so, then you need to add @Annotation to the _class_ doc comment of "Yitznewton\DocmasterBundle\Document\Document". If it is indeed no annotation, then you need to add @IgnoreAnnotation("Document") to the _class_ doc comment of class Yitznewton\DocmasterBundle\Document\Document.')
in /var/www/symfony-2.0.5/vendor/doctrine-common/lib/Doctrine/Common/Annotations/DocParser.php at line 613  -+
at DocParser ->Annotation ()
in /var/www/symfony-2.0.5/vendor/doctrine-common/lib/Doctrine/Common/Annotations/DocParser.php at line 518  -+
at DocParser ->Annotations ()
in /var/www/symfony-2.0.5/vendor/doctrine-common/lib/Doctrine/Common/Annotations/DocParser.php at line 283  -+
at DocParser ->parse ('/** @Document */', 'class Yitznewton\DocmasterBundle\Document\Document')
in /var/www/symfony-2.0.5/vendor/doctrine-common/lib/Doctrine/Common/Annotations/AnnotationReader.php at line 149  -+
at AnnotationReader ->getClassAnnotations (object(ReflectionClass))
in /var/www/symfony-2.0.5/vendor/doctrine-common/lib/Doctrine/Common/Annotations/FileCacheReader.php at line 63  -+
at FileCacheReader ->getClassAnnotations (object(ReflectionClass))
in /var/www/symfony-2.0.5/vendor/symfony/src/Symfony/Component/Validator/Mapping/Loader/AnnotationLoader.php at line 38  -+
at AnnotationLoader ->loadClassMetadata (object(ClassMetadata))
in /var/www/symfony-2.0.5/vendor/symfony/src/Symfony/Component/Validator/Mapping/Loader/LoaderChain.php at line 57  -+
at LoaderChain ->loadClassMetadata (object(ClassMetadata))
in /var/www/symfony-2.0.5/vendor/symfony/src/Symfony/Component/Validator/Mapping/ClassMetadataFactory.php at line 64  -+
at ClassMetadataFactory ->getClassMetadata ('Yitznewton\DocmasterBundle\Document\Document')
in /var/www/symfony-2.0.5/vendor/symfony/src/Symfony/Component/Form/Extension/Validator/ValidatorTypeGuesser.php at line 310  -+
at ValidatorTypeGuesser ->guess ('Yitznewton\DocmasterBundle\Document\Document', 'title', object(Closure))
in /var/www/symfony-2.0.5/vendor/symfony/src/Symfony/Component/Form/Extension/Validator/ValidatorTypeGuesser.php at line 39  -+
at ValidatorTypeGuesser ->guessType ('Yitznewton\DocmasterBundle\Document\Document', 'title')
in /var/www/symfony-2.0.5/vendor/symfony/src/Symfony/Component/Form/FormTypeGuesserChain.php at line 46  -+
at Symfony\Component\Form\{closure} (object(ValidatorTypeGuesser))
in /var/www/symfony-2.0.5/vendor/symfony/src/Symfony/Component/Form/FormTypeGuesserChain.php at line 85  -+
at FormTypeGuesserChain ->guess (object(Closure))
in /var/www/symfony-2.0.5/vendor/symfony/src/Symfony/Component/Form/FormTypeGuesserChain.php at line 47  -+
at FormTypeGuesserChain ->guessType ('Yitznewton\DocmasterBundle\Document\Document', 'title')
in /var/www/symfony-2.0.5/vendor/symfony/src/Symfony/Component/Form/FormFactory.php at line 309  -+
at FormFactory ->createBuilderForProperty ('Yitznewton\DocmasterBundle\Document\Document', 'title', null, array())
in /var/www/symfony-2.0.5/vendor/symfony/src/Symfony/Component/Form/FormBuilder.php at line 575  -+
at FormBuilder ->create ('title', null, array())
in /var/www/symfony-2.0.5/vendor/symfony/src/Symfony/Component/Form/FormBuilder.php at line 691  -+
at FormBuilder ->buildChildren ()
in /var/www/symfony-2.0.5/vendor/symfony/src/Symfony/Component/Form/FormBuilder.php at line 654  -+
at FormBuilder ->getForm ()
in /var/www/symfony-2.0.5/src/Yitznewton/DocmasterBundle/Controller/FrontendController.php at line 31  -

I couldn't see how my class is significantly different to those in the docs. Thank you!

Fetching referenced (many) documents fails when having multiple fields with the same mappedBy value

The method UnitOfWork ->assertValidDocumentType will fail, as currently all references are handled by the PersistentViewCollection, not only those matching the targetDocument.

I would suggest the view is extended to provide the type of the referenced document in the key and the related objects are fetched using the the target document in the key filter.

Alternatively the createDocument could be wrapped by a try/catch to filter invalid document type failures.

Best regards,
Sven

Query by type

I had a simple findAll() which returned 0 docs.

$documentManager->getRepository('Item')->findAll()

it turns out to be the doctrine metadata.
It was

doc.doctrine_metadata.indexed

I changed it to

doc.doctrine_metadata.indexes

and now the view returns the Item

Not sure how it happened.. Hope it helps someone one day

CouchDB ODM Error "A detached document was found through a relationship during cascading a persist operation."

This my CouchDB Documents:

use Doctrine\ODM\CouchDB\Mapping\Annotations as CouchDB;
use Doctrine\Common\Collections\ArrayCollection;

/**
 * @CouchDB\Document
 */
class Interest 
{

    /** @CouchDB\Id(strategy="ASSIGNED") */
    private $id;

    /** @CouchDB\Field(type="string") */
    private $name;

    /** @CouchDB\Field(type="string") */
    private $phone;

    /** @@CouchDB\ReferenceOne(targetDocument="User", cascade={"all"}) */
    private $address;

    /** @CouchDB\ReferenceMany(targetDocument="Activity", mappedBy="interests", cascade={"all"}) */
    private $activities;

    /** @CouchDB\Field(type="string") */
    private $website;

    public function __construct() 
    {
        $this->activities = new ArrayCollection;
    }

    public function setId($id) 
    {
        $this->id = $id;

        return $this;
    }

    public function getId() 
    {
        return $this->id;
    }

    public function getName() 
    {
        return $this->name;
    }

    public function setName($name) 
    {
        $this->name = $name;

        return $this;
    }

    public function setPhone($phone) 
    {
        $this->phone = $phone;

        return $this;
    }

    public function getPhone() 
    {
        return $this->phone;
    }

    public function setWebsite($website) 
    {
        $this->website = $website;

        return $this;
    }

    public function getWebsite() 
    {
        return $this->website;
    }

    public function getAddress() 
    {
        return $this->address;
    }

    public function setAddress(Address $address) 
    {
        $this->address = $address;

        return $this;
    }

    public function setActivities(array $activities) 
    {
        foreach ($activities as $activity) {
            $activityObj = new Activity();
            $activityObj->setName($activity);
            $activityObj->addInterest($this);
            $this->addActivity($activityObj);
        }

        return $this;
    }

    public function addActivity(Activity $activity) 
    {
        $this->activities[] = $activity;
        $activity->addInterest($this);

        return $this;
    }

    public function getActivities() 
    {
        return $this->activities;
    }
}
use Doctrine\ODM\CouchDB\Mapping\Annotations as CouchDB;

/**
 * @CouchDB\Document
 */
class Address 
{

    /** @CouchDB\Id(strategy="ASSIGNED") */
    private $id;

    /** @CouchDB\Field(type="integer") */
    private $zipcode;

    /** @CouchDB\Field(type="string") */
    private $address;

    /** @CouchDB\Field(type="mixed") */
    private $latitude;

    /** @CouchDB\Field(type="mixed") */
    private $longitude;

    public function getId()
    {
        return $this->id;
    }

    public function setId($id)
    {
        $this->id = $id;

        return $this;
    }

    public function getZipCode()
    {
        return $this->zipcode;
    }

    public function setZipCode($zipcode)
    {
        $this->zipcode = $zipcode;

        return $this;
    }

    public function getAddress()
    {
        return $this->address;
    }

    public function setAddress($address)
    {
        $this->address = $address;

        return $this;
    }

    public function getLatitude()
    {
        return $this->latitude;
    }

    public function setLatitude($latitude)
    {
        $this->latitude = $latitude;

        return $this;
    }

    public function getLongitude()
    {
        return $this->longitude;
    }

    public function setLongitude($longitude)
    {
        $this->longitude = $longitude;

        return $this;
    }
}
use Doctrine\ODM\CouchDB\Mapping\Annotations as CouchDB;
use Doctrine\Common\Collections\ArrayCollection;

/**
 * @CouchDB\Document
 */
class Activity 
{

    /** @CouchDB\Id(strategy="ASSIGNED") */
    private $id;

    /** @CouchDB\Field(type="string") */
    private $name;

    /** @CouchDB\ReferenceMany(targetDocument="Interest") */
    private $interests;

    public function __construct() 
    {
        $this->interests = new ArrayCollection;
    }

    public function setId($id) 
    {
        $this->id = $id;

        return $this;
    }

    public function getId() 
    {
        return $this->id;
    }

    public function setName($name) 
    {
        $this->name = $name;

        return $this;
    }

    public function getName() 
    {
        return $this->name;
    }

    public function addInterest(Interest $interest) 
    {
        $this->interests[] = $interest;
    }
}

Collection scan getting slower and slower

Hello

I have to scan a small collection from CouchDB (~150 object), apply some change and then flush the changes. Initially, it take a few seconds. When I repeat the process with other collections it takes more and more time. If I repeatedly run the scan on the same collection, it alos gets slower and slower (more than 1 mn at the end).

Cannot figure out what happens. I am using V1.Alpha2, I call a dm->clear() at the beginning. Any any where I could search for an explanation?

Thanks a lot

Philippe

Inconsistent serialization of embed-many

Sometimes an embed-many mapping is persisted to CouchDB as a JSON array; sometimes it is persisted as a JSON object.

When you first add an array of objects to a document, the document appears in CouchDB as the Doctrine documentation suggests it should. However if you later remove one of these objects and update the document, the relationship is persisted differently.

Using the example at http://docs.doctrine-project.org/projects/doctrine-couchdb/en/latest/reference/association-mapping.html#embedmany, this is how the document appears in the database when the objects are first added:

{
    "_id": "1234",
    "phonenumbers":
    [
        {"number": "+1234567890"},
        {"number": "+1234567891"},
        {"number": "+1234567892"}
    ]
}

And this is how it becomes when you remove one:

{
    "_id": "1234",
    "phonenumbers":
    {
        "0": {"number": "+1234567890"},
        "2": {"number": "+1234567892"}
    }
}

This happens because the embedded document serializer maintains the key-value mapping, and the behaviour of PHP's json_encode is inconsistent for arrays with integer keys. If the array has consecutive integer keys starting at zero, json_encode produces a JSON array. So for example:

$a = array("x", "y", "z");
var_dump(json_encode($a));

produces:

string(13) "["x","y","z"]"

If the keys do not start at zero, or are not consecutive, json_encode produces a JSON object. So for example:

$a = array("x", "y", "z");
unset($a[1]);
var_dump(json_encode($a));

produces:

string(17) "{"0":"x","2":"z"}"

The inconsistency can cause problems with map-reduce functions that need to traverse the array.

To fix this inconsistency, I believe the embedded document serializer should only maintain the key-value mappings when the array has non-integer (string) keys. If the array only contains integer keys, the keys should be renumbered to ensure json_encode always produces a JSON array.

Edit: The same problem occurs when using a "mixed" mapping for an array of strings, but we're already working around this by defining two custom types. Our "array" mapping forces a PHP array to be represented in CouchDB as a JSON array, and our "hash" mapping forces a PHP array to be represented as a JSON object.

How to use CouchDB ODM with Silex?

Compliments of the season.

I'm trying to configure this with silex but just can't crack it right now. Any guide,p or tuts would be great.

Thanks.

forcing the document ID fails with "Detached document passed to persist()"

I am trying to add a document using an Id that is chosen by my application, not by the odm.

/**
 * @CouchDB\Document(indexed=true)
 */
class TestCouch {
    /** @CouchDB\Id(type="string") */
    public $id;
    /** @CouchDb\Field(type="string") */
    public $contents;
    // ... etc
}

I use

$obj = new TestCouch();
$obj->setId('test-123'); // commenting this line will work, but I will receive an ID automatically, not what I want
$obj->setContents($data);
$documentManager->persist($obj);
$documentManager->flush();

Expected behaviour

Document is saved with _id value of test-123

Actual behaviour

The error I receive is Detached document passed to persist(). which in Symfony2 also translates into a 500 Internal Server Error.

Feature: Lifecycle Callbacks

It would be very useful to have DoctrineORM Lifecycle Callbacks in CouchdbODM, too.
http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/events.html#lifecycle-callbacks

Usecase:
If you save an object and after that you change the mapping information, for example add a embedOne field, then the new field is null if you load the object again. This is logical, but sometimes you want to set default values.

class Foo 
{

  /**
   * @CouchDB\EmbedOne()
   */
  private $bar;

  public function __construct()
  {
    $this->bar = new Bar();
  }

  /** @PostLoad */
  public function updateDefaultValues()
  {
    if($this->bar === null) {
      $this->bar = new Bar();
    }
  }

}

class Bar
{
  // ...
}

The same problem we have with EmbedMany fields. We save an ArrayCollection and we get back either null or an array.

Add converions according to $class->properties[$name]['type']

In the ORM we have the Doctrine\DBAL\Types namespace that we have to mirror to Doctrine\ODM\CouchDB\Types. Methods would have to be "convertPhpToJsonValue()" and "convertJsonToPhpValue()" that need to be called during hydration and saving inside the Persister.

Possible Types for now:

  • String (this is both VARCHAR + CLOB of DBs)
  • Integer
  • Array (uncasted values)
  • Float/Double
  • Boolean

Problem: Using all_or_nothing=true by default

We had several reports now that using the all or nothing strategy for documents leads to problems:

  • Creating conflict documents even though updates should be clean.
  • Performance drop in very large databases.

We should use the default CouchDB strategy all_or_nothing=false by default. This will be a huge BC break though.

Missing Interface

I got following message after composer update.

Fatal error: Interface 'Doctrine\ODM\CouchDB\Mapping\Driver\Driver' not found in /var/www/sp_dev/vendor/doctrine/couchdb-odm/lib/Doctrine/ODM/CouchDB/Mapping/Driver/DriverChain.php on line 20

Composer install fail

After I type this

composer require "doctrine/couchdb-odm:dev-master"

I got the following message

Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - The requested package doctrine/couchdb-odm could not be found in any version, there may be a typo in the package name.

Potential causes:
 - A typo in the package name
 - The package is not available in a stable-enough version according to your minimum-stability setting
   see <https://groups.google.com/d/topic/composer-dev/_g3ASeIFlrc/discussion> for more details.

Read <http://getcomposer.org/doc/articles/troubleshooting.md> for further common problems.

Installation failed, reverting ./composer.json to its original content.

How should I fix it ?

Thanks!

tests failing

doing a composer install --dev tests fail for me.

i have Apache CouchDB 1.0.1 - is there a minimal version required?

There were 6 failures:

1) Doctrine\Tests\ODM\CouchDB\Functional\CascadeRefreshTest::testCascadeRefresh
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-'Test!'
+'Test2'

/home/david/liip/symfony-cmf/doctrine/couchdb-odm/tests/Doctrine/Tests/ODM/CouchDB/Functional/CascadeRefreshTest.php:51
/usr/bin/phpunit:46

2) Doctrine\Tests\ODM\CouchDB\Functional\InheritenceTest::testPersistInheritanceReferenceOne
Failed asserting that MyCouchDBProxyNS\__CG__\Doctrine\Tests\ODM\CouchDB\Functional\CODM25Child Object (...) is an instance of class "Doctrine\Tests\ODM\CouchDB\Functional\CODM25ChildA".

/home/david/liip/symfony-cmf/doctrine/couchdb-odm/tests/Doctrine/Tests/ODM/CouchDB/Functional/InheritenceTest.php:23
/usr/bin/phpunit:46

3) Doctrine\Tests\ODM\CouchDB\Functional\ManyToOneAssociationTest::testSaveWithAssociation
CmsUser is a proxy, username is NULL through public access
Failed asserting that 'beberlei' is null.

/home/david/liip/symfony-cmf/doctrine/couchdb-odm/tests/Doctrine/Tests/ODM/CouchDB/Functional/ManyToOneAssociationTest.php:46
/usr/bin/phpunit:46

4) Doctrine\Tests\ODM\CouchDB\Functional\RepositoryTest::testFindAll
No results, group is not indexed!
Failed asserting that 10 matches expected 0.

/home/david/liip/symfony-cmf/doctrine/couchdb-odm/tests/Doctrine/Tests/ODM/CouchDB/Functional/RepositoryTest.php:81
/usr/bin/phpunit:46

5) Doctrine\Tests\ODM\CouchDB\Mapping\AnnotationDriverTest::testGetAllClassNamesReturnsAlreadyLoadedClassesIfAppropriate
Failed asserting that an array contains 'Doctrine\Tests\Models\CMS\CmsUser'.

/home/david/liip/symfony-cmf/doctrine/couchdb-odm/tests/Doctrine/Tests/ODM/CouchDB/Mapping/AnnotationDriverTest.php:39
/usr/bin/phpunit:46

6) Doctrine\Tests\ODM\CouchDB\Mapping\ClassMetadataFactoryTest::testGetMetadataForDocumentWithMappedSuperclass
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-'Doctrine\Tests\ODM\CouchDB\Mapping\Super'
+'Doctrine\Tests\ODM\CouchDB\Mapping\Child'

/home/david/liip/symfony-cmf/doctrine/couchdb-odm/tests/Doctrine/Tests/ODM/CouchDB/Mapping/ClassMetadataFactoryTest.php:38
/usr/bin/phpunit:46

FAILURES!
Tests: 188, Assertions: 535, Failures: 6, Incomplete: 1, Skipped: 26.

Indexes

I have an object that I have added a mapping for. I created a migration that updates the doctrine_metadata['indexes'] array. However, when I update an existing record, particularly when updating the indexed field, the index field name is from the indexes again.

I am well aware that I might be having a mapping issue, but here are the subelements I am using....

I am running this in Symfony2, with FOSUserBundle. I have replaced the bundle's mapping with class annotations, basically using FOSUserBundles Base class for the functionality. This is I am afraid where the issue is and somehow the DocumentManger is still loading the mapping from the Bundles XML files.

Thanks for the help.

Performance

First I'd like to emphasize I'm new to CouchDB/NoSQL and even if I've used Doctrine ORM for a few years now, I'm not an expert and I'm new to Doctrine ODM. So maybe the performance issues come from a misuse, misunderstanding, misconception or a bad configuration.

Let's say I have some kind of a tree structure with entities holding a relation to a parent entity (of the same type). Of course multiple entities of the same level may share the same parent entity.

Issue 1
Doctrine docs say the loading from the database is lazy and objects are really initialized whenever a method is called on the object. But when I fetch an entity with a find method or by querying a view with the include_doc parameter set to true, it turns out that not only Doctrine fully initialize the objects but it also fetch and initialize all related objects (and maybe all related objects of this related object and so on...) .

Issue 2
Doctrine fetch the same objet multiple times. Let's say I have 5 entities of the same level that share the same parent entity. Because of issue 1, Doctrine will need to access the parent entity 5 times. I thought Doctrine kept references to entities already fetched to avoid multiple fetches of the same entity but it turned out that Doctrine will fetch the parent entity 5 times...

Issue 3
From my understanding, an object will be fully initialized whenever a method is called. Given issues 1 and 2, this has major performance impact if you don't need other methods. I understand it avoids making multiple queries if multiple methods on the same object are called but maybe this behavior could be configurable so that a developer could choose the best strategy

To give you an exemple, for a tree containing 16 nodes on 2 levels, each low level node containing 2 documents for a total of 28 documents (2 nodes don't have any doc), Doctrine generates 51 requests to CouchDB ! On my development server it takes 4,1 seconds which is HUGE.

In my opinion, it should only generate 1 initial request + 16 other requests for the parent entities = 17 requests.

Needless to say I'm really scared about the performance I will get when I add more and more levels to the tree...

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.