doctrine for nosql
DESCRIPTION
This talk was held on International PHP Conference 2011 andTRANSCRIPT
![Page 1: Doctrine for NoSQL](https://reader031.vdocuments.us/reader031/viewer/2022020110/55512c10b4c905b3598b4b98/html5/thumbnails/1.jpg)
Doctrine NoSQL
Benjamin Eberlei (SimpleThings GmBH)
![Page 2: Doctrine for NoSQL](https://reader031.vdocuments.us/reader031/viewer/2022020110/55512c10b4c905b3598b4b98/html5/thumbnails/2.jpg)
About me
Benjamin EberleiWorking at SimpleThings GmBH
http://www.simplethings.deOpen Source contributor
Doctrine2, Symfony2(Zeta Components, PHPUnit, ...)
Twitter @beberleiBlog http://www.whitewashing.de
![Page 3: Doctrine for NoSQL](https://reader031.vdocuments.us/reader031/viewer/2022020110/55512c10b4c905b3598b4b98/html5/thumbnails/3.jpg)
The Doctrine Project
www.doctrine-project.org
The Doctrine Project is the home of a selectedset of PHP libraries primarily focused onproviding persistence services and relatedfunctionality.
![Page 4: Doctrine for NoSQL](https://reader031.vdocuments.us/reader031/viewer/2022020110/55512c10b4c905b3598b4b98/html5/thumbnails/4.jpg)
Doctrine Subprojects
DBAL and ORMDocument Mapper (MongoDB, CouchDB, PHPCR)AnnotationsXMLWhat is next?
![Page 5: Doctrine for NoSQL](https://reader031.vdocuments.us/reader031/viewer/2022020110/55512c10b4c905b3598b4b98/html5/thumbnails/5.jpg)
Doctrine Philosophy
Separating Persistance and Objects
![Page 6: Doctrine for NoSQL](https://reader031.vdocuments.us/reader031/viewer/2022020110/55512c10b4c905b3598b4b98/html5/thumbnails/6.jpg)
Doctrine Philosophy
Small common API - Similar look and feel
![Page 7: Doctrine for NoSQL](https://reader031.vdocuments.us/reader031/viewer/2022020110/55512c10b4c905b3598b4b98/html5/thumbnails/7.jpg)
Doctrine Philosphy
Embrace Differences
![Page 8: Doctrine for NoSQL](https://reader031.vdocuments.us/reader031/viewer/2022020110/55512c10b4c905b3598b4b98/html5/thumbnails/8.jpg)
Why NoSQL Mapper?
Schemaless storage allows storing:
Arbitrary associationsEmbedded objectsLists and Associative Arrays
No duplicate schema-maintenance!
![Page 9: Doctrine for NoSQL](https://reader031.vdocuments.us/reader031/viewer/2022020110/55512c10b4c905b3598b4b98/html5/thumbnails/9.jpg)
Doctrine NoSQL History
MongoDB Mapper early 2010 (OpenSky)CouchDB Mapper started in October 2010 (Liip)PHPCR ODM started in early 2011 (Liip)APIs heavily inspired from ORM
![Page 10: Doctrine for NoSQL](https://reader031.vdocuments.us/reader031/viewer/2022020110/55512c10b4c905b3598b4b98/html5/thumbnails/10.jpg)
SQL and NoSQL Similarities
Extracted common persistence interfacesCovering roughly 10-20% of the use-cases
Simple Finder MethodsInsert/Update/DeleteMetadata API
Support for Annotations/XML/YAML/PHP Mapping
![Page 11: Doctrine for NoSQL](https://reader031.vdocuments.us/reader031/viewer/2022020110/55512c10b4c905b3598b4b98/html5/thumbnails/11.jpg)
Persistence Interfaces<?phpinterface ObjectManager{ function find($class, $id); function getReference($class, $id); function persist($object); function remove($object); function flush();
function getClassMetadata($class); function getRepository($class);}
![Page 12: Doctrine for NoSQL](https://reader031.vdocuments.us/reader031/viewer/2022020110/55512c10b4c905b3598b4b98/html5/thumbnails/12.jpg)
Persistence Interfaces<?phpinterface ObjectRepository{ function find($id); function findAll(); function findBy(array $criteria, $orderBy = null, $limit = null, $offset = null ) function findOneBy(array $criteria);}
![Page 13: Doctrine for NoSQL](https://reader031.vdocuments.us/reader031/viewer/2022020110/55512c10b4c905b3598b4b98/html5/thumbnails/13.jpg)
Sample Document<?php/** @Document */class Message{ /** @Id */ public $id; /** @Field(type="string") */ public $text;}
$message = new Message();$message->setText("Hello World!");
![Page 14: Doctrine for NoSQL](https://reader031.vdocuments.us/reader031/viewer/2022020110/55512c10b4c905b3598b4b98/html5/thumbnails/14.jpg)
NoSQL benefits<?php/** @Document */class Product{ /** other fields */ /** @Field(type="array") */ public $attributes; /** @Field(type="array") */ public $translations;}
$product->attributes["isbn"] = "A-B-C-D";$product->translations["de"]["name"] = "Ein Produkt";
![Page 15: Doctrine for NoSQL](https://reader031.vdocuments.us/reader031/viewer/2022020110/55512c10b4c905b3598b4b98/html5/thumbnails/15.jpg)
Working with Objects 1
Creating a new document:
<?php/** @var $dm DocumentManager */$message = new Message();$message->setText("I am new!");
$dm->persist($message);$dm->flush();
echo "ID: " . $message->getId();
![Page 16: Doctrine for NoSQL](https://reader031.vdocuments.us/reader031/viewer/2022020110/55512c10b4c905b3598b4b98/html5/thumbnails/16.jpg)
Working with Objects 2
Find and update document:
<?php/** @var $dm DocumentManager */$message = $dm->find("Message", 1);$message->setText("New Message");$dm->flush();
![Page 17: Doctrine for NoSQL](https://reader031.vdocuments.us/reader031/viewer/2022020110/55512c10b4c905b3598b4b98/html5/thumbnails/17.jpg)
Working with Objects 3
Find and remove documents:
<?php/** @var $dm DocumentManager */$repository = $dm->getRepository("User");$criteria = array("status" => "inactive");$users = $repository->findBy($criteria);
foreach ($users AS $user) { $dm->remove($user);}$dm->flush();
![Page 18: Doctrine for NoSQL](https://reader031.vdocuments.us/reader031/viewer/2022020110/55512c10b4c905b3598b4b98/html5/thumbnails/18.jpg)
Persistence API Use-Cases
No query abstractionFocus on "in memory" object workflowsSpecialized reusable Modules for FrameworksSymfony2:
User ManagementCommentAdmin Generatorslichess
![Page 19: Doctrine for NoSQL](https://reader031.vdocuments.us/reader031/viewer/2022020110/55512c10b4c905b3598b4b98/html5/thumbnails/19.jpg)
Associations in NoSQL
Cons
No referential integrityNo support for transactions
Pros
Embedded DocumentsAdhoc references of arbitrary types
![Page 20: Doctrine for NoSQL](https://reader031.vdocuments.us/reader031/viewer/2022020110/55512c10b4c905b3598b4b98/html5/thumbnails/20.jpg)
Association Mappings<?php/** @Document */class Blog{ /** @ReferenceMany */ private $articles; /** @ReferenceOne(targetDocument="User") */ private $owner;}
![Page 21: Doctrine for NoSQL](https://reader031.vdocuments.us/reader031/viewer/2022020110/55512c10b4c905b3598b4b98/html5/thumbnails/21.jpg)
Association keys<?php$id = "1";$articleSlug = "hello-world";
$blog = $dm->find("Blog", $id);$blog->articles[$articleSlug]->getHeadline();
![Page 22: Doctrine for NoSQL](https://reader031.vdocuments.us/reader031/viewer/2022020110/55512c10b4c905b3598b4b98/html5/thumbnails/22.jpg)
Embedded Mappings<?php/** @Document */class User{ /** @EmbedMany */ private $phonenumbers; /** @EmbedOne(targetDocument="Address") */ private $address;}
![Page 23: Doctrine for NoSQL](https://reader031.vdocuments.us/reader031/viewer/2022020110/55512c10b4c905b3598b4b98/html5/thumbnails/23.jpg)
CouchDB and Doctrine
JSON DatastorageHTTP/REST APIMVCC, eventually consistent (Conflicts)ReplicationAttachmentsViews and Map/Reduce in JavascriptCouchDB LuceneDoctrine CouchDB 1.0 Alpha 1
![Page 24: Doctrine for NoSQL](https://reader031.vdocuments.us/reader031/viewer/2022020110/55512c10b4c905b3598b4b98/html5/thumbnails/24.jpg)
JSON Document{ "_id": "716104ac33c797b12d50c0a6483f1661", "_rev": "1-32db404b78f130fd8f7575905859e19b", "doctrine_metadata": { "type": "MyProject.Document.Message", "associations": { "user": "055fe8a3ab06c3998d27b6d99f5a9bdd" } }, "message": "I am a message"}
![Page 25: Doctrine for NoSQL](https://reader031.vdocuments.us/reader031/viewer/2022020110/55512c10b4c905b3598b4b98/html5/thumbnails/25.jpg)
Document Version
Implement Optimistic-Locking
<?phpclass Article{ /** @Version */ private $version;}
$article = $dm->find( "Article", $id, $expectedVersion);
![Page 26: Doctrine for NoSQL](https://reader031.vdocuments.us/reader031/viewer/2022020110/55512c10b4c905b3598b4b98/html5/thumbnails/26.jpg)
Attachments
CouchDB supports Attachments to documentsDoctrine converts into Attachment objectLazy Load binary data from the serverStream support planned
<?phpclass Article{ /** @Attachments */ public $attachments = array();}
![Page 27: Doctrine for NoSQL](https://reader031.vdocuments.us/reader031/viewer/2022020110/55512c10b4c905b3598b4b98/html5/thumbnails/27.jpg)
Attachments 2<?phpuse Doctrine\CouchDB\Attachment;
$article = $dm->find("Article", 1);$data = $article->attachments["teaser.jpg"]->getContent();
$a = Attachment::createFromBase64data($data, "image/jpg");$article->attachments["author.jpg"] = $a;
$dm->flush();
![Page 28: Doctrine for NoSQL](https://reader031.vdocuments.us/reader031/viewer/2022020110/55512c10b4c905b3598b4b98/html5/thumbnails/28.jpg)
Views
Doctrine CouchDB maps filesystem to design document:
application/ couchdb/ views/ username/ map.js reduce.js
Use javascript syntax higlighting in your IDE/Editor.
![Page 29: Doctrine for NoSQL](https://reader031.vdocuments.us/reader031/viewer/2022020110/55512c10b4c905b3598b4b98/html5/thumbnails/29.jpg)
Views 2<?phpuse Doctrine\CouchDB\View\FileFolderDesignDocument;
$path = "/path/application/couchdb";$designDoc = new FileFolderDesignDocument($path);
/* @doc $couch CouchClient */$docName = "myapp";$couch->createDesignDoc($docName, $designDoc);
![Page 30: Doctrine for NoSQL](https://reader031.vdocuments.us/reader031/viewer/2022020110/55512c10b4c905b3598b4b98/html5/thumbnails/30.jpg)
Query Views<?php/* @var $dm DocumentManager */$query = $dm->createQuery("myapp", "username");$result = $query->setStartKey("b") ->setEndKey("c") ->setLimit(10) ->setSkip(10) ->includeDocs(true) ->execute();
Using include docs creates PHP instances for you.
![Page 31: Doctrine for NoSQL](https://reader031.vdocuments.us/reader031/viewer/2022020110/55512c10b4c905b3598b4b98/html5/thumbnails/31.jpg)
Lucene Queries
Support for the CouchDB Lucene extension:
<?php$query = $dm->createLuceneQuery("lucenedoc", "users");$result = $query->setQuery('"John Galt" OR "John Wayne"') ->setLimit(10) ->setSkip(10) ->includeDocs(true) ->execute();
![Page 32: Doctrine for NoSQL](https://reader031.vdocuments.us/reader031/viewer/2022020110/55512c10b4c905b3598b4b98/html5/thumbnails/32.jpg)
MongoDB and Doctrine
Indexing and on the flyqueriesVery fastIn-Place Updates²GridFS, GeolocationShardingDoctrine MongoDB 1.0 Beta2
![Page 33: Doctrine for NoSQL](https://reader031.vdocuments.us/reader031/viewer/2022020110/55512c10b4c905b3598b4b98/html5/thumbnails/33.jpg)
Complex Associations<?phpclass User{ /** * @ReferenceMany( * targetDocument="Comment", * mappedBy="blogPost", * sort={"date"="desc"}, * limit=5) */ private $last5Comments;}
![Page 34: Doctrine for NoSQL](https://reader031.vdocuments.us/reader031/viewer/2022020110/55512c10b4c905b3598b4b98/html5/thumbnails/34.jpg)
Query API<?php$qb = $dm->createQueryBuilder('User') ->field('groups') ->all(array('Group 1', 'Group 2')) ->sort("username", "asc") ->limit(10) ->skip(10) ->execute();
![Page 35: Doctrine for NoSQL](https://reader031.vdocuments.us/reader031/viewer/2022020110/55512c10b4c905b3598b4b98/html5/thumbnails/35.jpg)
Map/Reduce<?php$qb = $dm->createQueryBuilder('Documents\User') ->field('type')->equals('sale') ->map('function() { emit(this.user.$id, 1); }') ->reduce('function(k, vals) { var sum = 0; for (var i in vals) { sum += vals[i]; } return sum; }');
![Page 36: Doctrine for NoSQL](https://reader031.vdocuments.us/reader031/viewer/2022020110/55512c10b4c905b3598b4b98/html5/thumbnails/36.jpg)
Geospatial Queries<?php/** @Document @Index(keys={"coordinates"="2d"}) */class City{ /** @EmbedOne(targetDocument="Coordinates") */ public $coordinates; /** @Distance */ public $distance;}class Coordinates{ public $lat; public $long;}
![Page 37: Doctrine for NoSQL](https://reader031.vdocuments.us/reader031/viewer/2022020110/55512c10b4c905b3598b4b98/html5/thumbnails/37.jpg)
Geospatial Queries 2
Execute a Geospatial query and find locations near a point:
<?php/* @var $dm DocumentManager */$cities = $dm->createQuery('City') ->field('coordinates')->near(50, 60) ->execute();
![Page 38: Doctrine for NoSQL](https://reader031.vdocuments.us/reader031/viewer/2022020110/55512c10b4c905b3598b4b98/html5/thumbnails/38.jpg)
Eventual Migration
Handle simple and complex schema refactorings
<?phpclass Person{ public $id;
/** @AlsoLoad("name") */ public $fullName;}
![Page 39: Doctrine for NoSQL](https://reader031.vdocuments.us/reader031/viewer/2022020110/55512c10b4c905b3598b4b98/html5/thumbnails/39.jpg)
More of Doctrine MongoDB
Support for TreesSupport for Files in MongoGridFSCapped CollectionsTailable Cursors
![Page 40: Doctrine for NoSQL](https://reader031.vdocuments.us/reader031/viewer/2022020110/55512c10b4c905b3598b4b98/html5/thumbnails/40.jpg)
PHPCR ODM
PHP Content Repository ProjectPort of the Java Content Repository APIPHP API for Apache JackrabbitDoctrine PHPCR ODMs creates objects from Content Repositories.
![Page 41: Doctrine for NoSQL](https://reader031.vdocuments.us/reader031/viewer/2022020110/55512c10b4c905b3598b4b98/html5/thumbnails/41.jpg)
Object to XML Mapper
Convert objects to XML documents and back
<?php$user = new User();$user->setFirstName('John');$user->setLastName('Doe');$user->setAddress(new Address('123 Street', 'New Haven'));$user->addContact(new CustomerContact('[email protected]'));
$xml = $marshaller->marshalToString($user);$user = $marshaller->unmarshalFromString($xml);
![Page 42: Doctrine for NoSQL](https://reader031.vdocuments.us/reader031/viewer/2022020110/55512c10b4c905b3598b4b98/html5/thumbnails/42.jpg)
Using Doctrine 2.0.x ORM?
Please checkout 2.1 BETA1
It is backwards compatibleYou win a present if you can prove otherwise.
![Page 43: Doctrine for NoSQL](https://reader031.vdocuments.us/reader031/viewer/2022020110/55512c10b4c905b3598b4b98/html5/thumbnails/43.jpg)
Thank you!
Rate this talk:
http://joind.in/talk/view/3515