Slide 1

Slide 1 text

Sylius and MongoDB It’s not just changing connection strings

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

MongoDB and Sylius It’s not a simple story

Slide 4

Slide 4 text

Let’s talk about schemas

Slide 5

Slide 5 text

Relational databases Some say they are simple • Normalisation rules help us design “good” schemas • Have a primary key, add everything that depends on this primary key • If it’s not directly related to the primary key, extract it • ??? • Pro fi t!

Slide 6

Slide 6 text

MongoDB Schemas are just as complicated • MongoDB is not “schemaless” • It has a schema, but it is fl exible • It avoids some constraints from relational databases • After all, they’re from the 1970s

Slide 7

Slide 7 text

Don’t think about storing data

Slide 8

Slide 8 text

Think about consuming it

Slide 9

Slide 9 text

Example Address Book Data { "name": "alcaeus", "email": [ "", "" ], "phone": [ "", "" ] }

Slide 10

Slide 10 text

Example Fancy Address Book Data { "name": "alcaeus", "email": [ { "type": "work", "address": "" }, { "type": "private", "address": "" } ], "phone": [ { "type": "mobile", "number": "" }, { "type": "home", "number": "" } ] }

Slide 11

Slide 11 text

Time for Queries Everybody loves queries, right? SELECT entry.* from entry JOIN email ON email.entry_id = entry.id WHERE email.address = 'something';

Slide 12

Slide 12 text

Effects of Normalisation Does it help? • Need to join across tables to fi nd our main record • Only get main data • Multiple queries required to fetch rest of data • Alternative: complicated result preparation • How does this help?

Slide 13

Slide 13 text

Time for Queries #2 I love THOSE queries { "email.address": "something" }

Slide 14

Slide 14 text

Normalisation is a Relic

Slide 15

Slide 15 text

Sylius and MongoDB

Slide 16

Slide 16 text

Sylius and MongoDB What’s the big problem? • Sylius uses Doctrine ORM • Doctrine ORM and Doctrine MongoDB ODM are very similar • Interfaces are shared, entities can be shared • How hard can it be?

Slide 17

Slide 17 text

Read ORM mappings in ODM?

Slide 18

Slide 18 text

ERD Product

Slide 19

Slide 19 text

From ERD to Tables From Many to More CREATE TABLE sylius_channel (...); 
 
 CREATE TABLE sylius_product_option (...); 
 CREATE TABLE sylius_product_option_translation (...); 
 CREATE TABLE sylius_product_option_value (...); 
 CREATE TABLE sylius_product_option_value_translation (...); 
 CREATE TABLE sylius_product_attribute (...); 
 CREATE TABLE sylius_product_attribute_translation (…); 
 CREATE TABLE sylius_taxon (...); 
 CREATE TABLE sylius_taxon_translation (...); 
 CREATE TABLE sylius_product (...); 
 CREATE TABLE sylius_product_translation (...); 
 CREATE TABLE sylius_product_image (...); 
 CREATE TABLE sylius_product_attribute_value (...); 
 CREATE TABLE sylius_product_channels (...); 
 CREATE TABLE sylius_product_taxon (...); 
 CREATE TABLE sylius_product_options (...); 
 CREATE TABLE sylius_product_variant (...); 
 CREATE TABLE sylius_product_variant_option_value (...); 
 CREATE TABLE sylius_channel_pricing (...);

Slide 20

Slide 20 text

From Tables to Collections Making use of advanced schema types • References point to related data • Embedded documents include all related data • Could be used in relational databases (jsonb / complex types) • Advantages to both • It’s important to understand when to choose which

Slide 21

Slide 21 text

Taxons Embedded Translations { "_id": "...", "code": "...", "translations": { "en": { "slug": "hardware", "name": "Hardware", "description": "..." }, "de": { "slug": "hardware", "name": "Hardware", "description": "..." } } }

Slide 22

Slide 22 text

Taxons Simpli fi ed Translations { "_id": "...", "code": "...", "slug": { "en": "hardware", "de": "hardware" }, "name": { "en": "Hardware", "de": "Hardware" }, "description": { "en": "...", "de": "..." } }

Slide 23

Slide 23 text

Options Embedded Values { "_id": "...", "code": "length", "name": { "en": "Length", "de": "Länge" }, "values": [ { “code": "length-1-m“, "value": { "en": "3 ft", "de": "1 m" } } ] }

Slide 24

Slide 24 text

Product Referencing Options { "_id": "...", "code": "lightning-cable", "options": [ "...", "...", "..." ] }

Slide 25

Slide 25 text

Product ODM References { "_id": "...", "code": "lightning-cable", "options": [ { "ref": "sylius_product_option", "id": "..." }, { "ref": "sylius_product_option", "id": "..." }, { "ref": "sylius_product_option", "id": "..." } ] }

Slide 26

Slide 26 text

These mappings require effort

Slide 27

Slide 27 text

But we’re just getting started

Slide 28

Slide 28 text

Referencing or embedding? Is there another way? • Example: linking product variants and their option values • We don’t own the data, so we should use references • We don’t want to join, so embedded data would be best • We can’t reference an embedded document • Why not do both?

Slide 29

Slide 29 text

Product Hybrid References { "_id": "...", "code": "lightning-cable", "options": [ { "ref": "sylius_product_option", "id": "...", "code": "length", "name": { "en": "Length", "de": "Länge" } } ] }

Slide 30

Slide 30 text

Product Variant Hybrid References { "_id": "...", "code": "lightning-cable-1-m", "position": 0, "options": { "length": { "code": "length-1-m", "value": { "en": "3 ft", "de": "1 m" } } } }

Slide 31

Slide 31 text

Product Variant Embed All The Variants? { "_id": "...", "code": "lightning-cable", "options": [ ... ], "variants": [ { "code": "lightning-cable-1-m", "options": { "length": { "code": "length-1-m", "value": { "en": "3 ft", "de": "1 m" } } } } ] }

Slide 32

Slide 32 text

Transactions

Slide 33

Slide 33 text

Transactions Quick facts • MongoDB is ACID compliant • You can run multi-document transactions • No nested transactions • Good schema design can help you avoid them • Doctrine MongoDB ODM doesn’t support them

Slide 34

Slide 34 text

Transactions In a nutshell • Start transaction • Do your business logic • Commit transaction • (Or abort if you’ve decided otherwise) • Rollback on error

Slide 35

Slide 35 text

Transactions In MongoDB $session = $client->startSession(); $session->startTransaction(); // Complex database logic here $session->commitTransaction();

Slide 36

Slide 36 text

Transactions Retry Failed Commits $session->startTransaction(); // Complex database logic here while (1) { try { $session->commitTransaction(); } catch (RuntimeException $e) { if ( $e->getCode() !== 50 /* MaxTimeMSExpired */ && $e->hasErrorLabel('UnknownTransactionCommitResult') ) { // Retry committing the transaction continue; } throw $e; } }

Slide 37

Slide 37 text

Transactions Retry Failed Transactions while (1) { $session->startTransaction(); // Complex database logic here while (1) { try { $session->commitTransaction(); } catch (RuntimeException $e) { if ( $e->getCode() !== 50 /* MaxTimeMSExpired */ && $e->hasErrorLabel('UnknownTransactionCommitResult') ) { // Retry committing the transaction continue; } if ( $e->hasErrorLabel('TransientTransactionError') ) { // Restart transaction continue 2; } throw $e; } } }

Slide 38

Slide 38 text

Transactions Keep It Simple $doComplexDatabaseLogic = function (Session $session): void { // Complex database logic here }; $session = $client->startSession(); \MongoDB\with_transaction( $session, $doComplexDatabaseLogic, );

Slide 39

Slide 39 text

Transactions With Doctrine MongoDB ODM $session = $client->startSession(); \MongoDB\with_transaction( $session, function (Session $session) use ($documentManager): void { $documentManager->flush(['session' => $session]); } );

Slide 40

Slide 40 text

Transactions With Doctrine MongoDB ODM $session = $client->startSession();

Slide 41

Slide 41 text

What’s Next?

Slide 42

Slide 42 text

The ecosystem needs updating

Slide 43

Slide 43 text

Ecosystem Updates Doctrine MongoDB ODM • Support transactions in UnitOfWork • Support new update mechanisms • Support hybrid references • Support updating hybrid references

Slide 44

Slide 44 text

Ecosystem Updates Doctrine Extensions • Update Translation extension to leverage embedded documents • Update Tree extension to support nested set in ODM • Update Sortable extension to support ODM

Slide 45

Slide 45 text

Ecosystem Updates Sylius • Create mapping fi les for Doctrine MongoDB ODM • Create repositories and rewrite queries

Slide 46

Slide 46 text

Open Source needs YOU

Slide 47

Slide 47 text

Thanks! @alcaeus github.com/alcaeus symfony-devs: @alcaeus