Date post: | 12-May-2015 |
Category: |
Documents |
Upload: | benjamin-eberlei |
View: | 3,774 times |
Download: | 9 times |
Doctrine NoSQL
Benjamin Eberlei (SimpleThings GmBH)
About me
Benjamin EberleiWorking at SimpleThings GmBH
http://www.simplethings.deOpen Source contributor
Doctrine2, Symfony2(Zeta Components, PHPUnit, ...)
Twitter @beberleiBlog http://www.whitewashing.de
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.
Doctrine Subprojects
DBAL and ORMDocument Mapper (MongoDB, CouchDB, PHPCR)AnnotationsXMLWhat is next?
Doctrine Philosophy
Separating Persistance and Objects
Doctrine Philosophy
Small common API - Similar look and feel
Doctrine Philosphy
Embrace Differences
Why NoSQL Mapper?
Schemaless storage allows storing:
Arbitrary associationsEmbedded objectsLists and Associative Arrays
No duplicate schema-maintenance!
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
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
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);}
Persistence Interfaces<?phpinterface ObjectRepository{ function find($id); function findAll(); function findBy(array $criteria, $orderBy = null, $limit = null, $offset = null ) function findOneBy(array $criteria);}
Sample Document<?php/** @Document */class Message{ /** @Id */ public $id; /** @Field(type="string") */ public $text;}
$message = new Message();$message->setText("Hello World!");
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";
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();
Working with Objects 2
Find and update document:
<?php/** @var $dm DocumentManager */$message = $dm->find("Message", 1);$message->setText("New Message");$dm->flush();
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();
Persistence API Use-Cases
No query abstractionFocus on "in memory" object workflowsSpecialized reusable Modules for FrameworksSymfony2:
User ManagementCommentAdmin Generatorslichess
Associations in NoSQL
Cons
No referential integrityNo support for transactions
Pros
Embedded DocumentsAdhoc references of arbitrary types
Association Mappings<?php/** @Document */class Blog{ /** @ReferenceMany */ private $articles; /** @ReferenceOne(targetDocument="User") */ private $owner;}
Association keys<?php$id = "1";$articleSlug = "hello-world";
$blog = $dm->find("Blog", $id);$blog->articles[$articleSlug]->getHeadline();
Embedded Mappings<?php/** @Document */class User{ /** @EmbedMany */ private $phonenumbers; /** @EmbedOne(targetDocument="Address") */ private $address;}
CouchDB and Doctrine
JSON DatastorageHTTP/REST APIMVCC, eventually consistent (Conflicts)ReplicationAttachmentsViews and Map/Reduce in JavascriptCouchDB LuceneDoctrine CouchDB 1.0 Alpha 1
JSON Document{ "_id": "716104ac33c797b12d50c0a6483f1661", "_rev": "1-32db404b78f130fd8f7575905859e19b", "doctrine_metadata": { "type": "MyProject.Document.Message", "associations": { "user": "055fe8a3ab06c3998d27b6d99f5a9bdd" } }, "message": "I am a message"}
Document Version
Implement Optimistic-Locking
<?phpclass Article{ /** @Version */ private $version;}
$article = $dm->find( "Article", $id, $expectedVersion);
Attachments
CouchDB supports Attachments to documentsDoctrine converts into Attachment objectLazy Load binary data from the serverStream support planned
<?phpclass Article{ /** @Attachments */ public $attachments = array();}
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();
Views
Doctrine CouchDB maps filesystem to design document:
application/ couchdb/ views/ username/ map.js reduce.js
Use javascript syntax higlighting in your IDE/Editor.
Views 2<?phpuse Doctrine\CouchDB\View\FileFolderDesignDocument;
$path = "/path/application/couchdb";$designDoc = new FileFolderDesignDocument($path);
/* @doc $couch CouchClient */$docName = "myapp";$couch->createDesignDoc($docName, $designDoc);
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.
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();
MongoDB and Doctrine
Indexing and on the flyqueriesVery fastIn-Place Updates²GridFS, GeolocationShardingDoctrine MongoDB 1.0 Beta2
Complex Associations<?phpclass User{ /** * @ReferenceMany( * targetDocument="Comment", * mappedBy="blogPost", * sort={"date"="desc"}, * limit=5) */ private $last5Comments;}
Query API<?php$qb = $dm->createQueryBuilder('User') ->field('groups') ->all(array('Group 1', 'Group 2')) ->sort("username", "asc") ->limit(10) ->skip(10) ->execute();
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; }');
Geospatial Queries<?php/** @Document @Index(keys={"coordinates"="2d"}) */class City{ /** @EmbedOne(targetDocument="Coordinates") */ public $coordinates; /** @Distance */ public $distance;}class Coordinates{ public $lat; public $long;}
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();
Eventual Migration
Handle simple and complex schema refactorings
<?phpclass Person{ public $id;
/** @AlsoLoad("name") */ public $fullName;}
More of Doctrine MongoDB
Support for TreesSupport for Files in MongoGridFSCapped CollectionsTailable Cursors
PHPCR ODM
PHP Content Repository ProjectPort of the Java Content Repository APIPHP API for Apache JackrabbitDoctrine PHPCR ODMs creates objects from Content Repositories.
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);
Using Doctrine 2.0.x ORM?
Please checkout 2.1 BETA1
It is backwards compatibleYou win a present if you can prove otherwise.
Thank you!
Rate this talk:
http://joind.in/talk/view/3515