com presentations: Added the new MongoDB talk for Brighton PHP: document-complex.xml mongo-brightonphp16.xml slides/mongodb/checkin1.png slides/mongodb/checkin2.png slides/mongodb/clink.gif slides/mongodb/clinked-0.png slides/mongodb/clinked-1.png slides/mongodb/clinks.xml slides/mongodb/clinks1.xml slides/mongodb/clinks2.xml slides/mongodb/clinks3.xml slides/mongodb/clinks4.xml slides/mongodb/clinks5.xml slides/mongodb/collection.jpg slides/mong
[email protected] (Derick Rethans) Mon, 21 Mar 2016 14:29:24 +0000
| Newsgroups | php.pres |
|---|---|
| Message-ID | <[email protected]> |
Commit: b054e9549e4db7ad5703345c0d4a60e3e466f9fd Author: Derick Rethans <[email protected]> Mon, 21 Mar 2016 14:29:24 +0000 Parents: 997cbc9539aaa44913167d0620033e760b129a22 Branches: master Link: http://git.php.net/?p=presentations.git;a=commitdiff;h=b054e9549e4db7ad5703345c0d4a60e3e466f9fd Log: Added the new MongoDB talk for Brighton PHP Changed paths: A document-complex.xml A mongo-brightonphp16.xml A slides/mongodb/checkin1.png A slides/mongodb/checkin2.png A slides/mongodb/clink.gif A slides/mongodb/clinked-0.png A slides/mongodb/clinked-1.png A slides/mongodb/clinks.xml A slides/mongodb/clinks1.xml A slides/mongodb/clinks2.xml A slides/mongodb/clinks3.xml A slides/mongodb/clinks4.xml A slides/mongodb/clinks5.xml A slides/mongodb/collection.jpg A slides/mongodb/collections-title.xml A slides/mongodb/collections.xml M slides/mongodb/considerations.xml A slides/mongodb/data-model.xml A slides/mongodb/document-complex.xml M slides/mongodb/document-simple.xml A slides/mongodb/document-title.xml A slides/mongodb/document.jpg A slides/mongodb/dram-erd-in-mongo.xml A slides/mongodb/dram-erd.xml A slides/mongodb/dram.io.mongo2.png A slides/mongodb/dram.io.png M slides/mongodb/embed-vs-link.xml A slides/mongodb/index-title.xml A slides/mongodb/index.xml A slides/mongodb/indexes-explain.xml A slides/mongodb/indexes-explain2.xml A slides/mongodb/indexes-explain3.xml A slides/mongodb/indexes-new.xml A slides/mongodb/indexes-php.xml A slides/mongodb/indexes-special.xml A slides/mongodb/indexes-title.xml A slides/mongodb/indexes.jpg A slides/mongodb/keys-title.xml A slides/mongodb/keys.jpg A slides/mongodb/phplib-crud.xml A slides/mongodb/phplib-index.xml A slides/mongodb/phplib-intro.xml A slides/mongodb/phplib-title.xml A slides/mongodb/phplib.jpg A slides/mongodb/queries.jpg M slides/mongodb/questions.xml M slides/mongodb/tip-array-key.xml M slides/mongodb/tip-paged-result.xml A slides/mongodb/whisky-checking.xml A slides/mongodb/whisky-words.png A slides/mongodb/whisky-words.xml A style-black.css A style-black.xml
diff_b054e9549e4db7ad5703345c0d4a60e3e466f9fd.txt
(text/plain, 39.3 KB)
diff --git a/document-complex.xml b/document-complex.xml
new file mode 100644
index 0000000..e30d414
--- /dev/null
+++ b/document-complex.xml
@@ -0,0 +1,55 @@
+<slide>
+<title>Documents: Complex</title>
+
+<div effect="fade-out">
+<example>
+{
+ "_id" : "derick@localhost",
+ "fullname" : "Derick Rethans",
+ "slug" : "derick-rethans",
+ "created_at" : 1452546141,
+ "password" : "2874ce0de14f5451a3a48baf75f18b7962b21a367f3b21f14c4df33cdaaae25c",
+ "timezone" : "Europe/London",
+ "confirmed" : true,
+ "confirmed_at" : 1452546148,
+ "validation_code" : "4c96e43d7019b62a9f8fb137c96271c8",
+ "moderated" : false,
+ "location" : "London, UK",
+ "count" : 16,
+ "count_unique" : 13,
+ "badges" : [
+ "unique1",
+ "unique5",
+ "age21:1"
+ ],
+ "login_last" : 1458241395,
+ "login_count" : 146,
+ "read_last" : 1457902445,
+ "words" : [
+ "derick",
+ "rethans",
+ "london",
+ "uk"
+ ],
+ "isAdmin" : true
+}
+</example>
+</div>
+
+<div effect="fade-in-out">
+<example inline="1">
+</example>
+<list>
+<bullet>%_id%: immutable unique key of document</bullet>
+</list>
+</div>
+
+<div effect="fade-in stop">
+<example inline="1">
+</example>
+<list>
+<bullet>%_id%: immutable unique key of document</bullet>
+<bullet>All strings are UTF-8</bullet>
+</list>
+</div>
+</slide>
diff --git a/mongo-brightonphp16.xml b/mongo-brightonphp16.xml
new file mode 100644
index 0000000..f1bb0ea
--- /dev/null
+++ b/mongo-brightonphp16.xml
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="utf-8"?>
+<presentation css="10gen-strict.css">
+<topic>mongoDB</topic>
+<title>Database Schema Design for MongoDB</title>
+<event>Brighton PHP</event>
+<location>Brighton, UK</location>
+<date>March 21, 2016</date>
+<speaker>Derick Rethans</speaker>
+<email>[email protected]</email>
+<twitter>derickr</twitter>
+<url>http://derickrethans.nl/talks.html</url>
+<joindin></joindin>
+<slide>slides/mongodb/title.xml</slide>
+<slide>slides/mongodb/me.xml</slide>
+
+<slide>slides/mongodb/databasefield.xml</slide>
+<slide>slides/mongodb/nosql.xml</slide>
+
+** Terms **
+
+<slide>slides/mongodb/collections-documents.xml</slide>
+
+<slide>slides/mongodb/document-title.xml</slide>
+<slide>slides/mongodb/document-simple.xml</slide>
+<slide>slides/mongodb/document-complex.xml</slide>
+
+<slide>slides/mongodb/collections-title.xml</slide>
+<slide>slides/mongodb/collections.xml</slide>
+
+<slide>slides/mongodb/index-title.xml</slide>
+<slide>slides/mongodb/index.xml</slide>
+
+** From PHP **
+
+<slide>slides/mongodb/phplib-title.xml</slide>
+<slide>slides/mongodb/phplib-intro.xml</slide>
+<slide>slides/mongodb/phplib-crud.xml</slide>
+<slide>slides/mongodb/phplib-index.xml</slide>
+
+<slide>slides/mongodb/keys-title.xml</slide>
+<slide>slides/mongodb/data-model.xml</slide>
+<slide>slides/mongodb/considerations.xml</slide>
+
+Common Patterns
+
+- RDBMS-normalisation.
+
+<slide>slides/mongodb/eav.xml</slide>
+<slide>slides/mongodb/eav2.xml</slide>
+<slide>slides/mongodb/eav3.xml</slide>
+
+<slide>slides/mongodb/dram-erd.xml</slide>
+<slide>slides/mongodb/dram-erd-in-mongo.xml</slide>
+<slide>slides/mongodb/whisky-words.xml</slide>
+<slide>slides/mongodb/whisky-checking.xml</slide>
+
+<slide>slides/mongodb/clinks.xml</slide>
+<slide>slides/mongodb/clinks1.xml</slide>
+<slide>slides/mongodb/clinks2.xml</slide>
+<slide>slides/mongodb/clinks3.xml</slide>
+<slide>slides/mongodb/clinks4.xml</slide>
+<slide>slides/mongodb/clinks5.xml</slide>
+
+<slide>slides/mongodb/document-validation.xml</slide>
+
+<slide>slides/mongodb/embed-vs-link.xml</slide>
+
+<slide>slides/mongodb/index-title.xml</slide>
+<slide>slides/mongodb/indexes-new.xml</slide>
+<slide>slides/mongodb/indexes-php.xml</slide>
+<slide>slides/mongodb/indexes-explain.xml</slide>
+<slide>slides/mongodb/indexes-explain2.xml</slide>
+<slide>slides/mongodb/indexes-explain3.xml</slide>
+<slide>slides/mongodb/indexes-special.xml</slide>
+
+<slide>slides/mongodb/questions.xml</slide>
+<slide>slides/mongodb/mongodbworld16.xml</slide>
+<slide>slides/mongodb/resources.xml</slide>
+
+</presentation>
diff --git a/slides/mongodb/checkin1.png b/slides/mongodb/checkin1.png
new file mode 100644
index 0000000..855e3f0
Binary files /dev/null and b/slides/mongodb/checkin1.png differ
diff --git a/slides/mongodb/checkin2.png b/slides/mongodb/checkin2.png
new file mode 100644
index 0000000..722ea5c
Binary files /dev/null and b/slides/mongodb/checkin2.png differ
diff --git a/slides/mongodb/clink.gif b/slides/mongodb/clink.gif
new file mode 100644
index 0000000..badd09b
Binary files /dev/null and b/slides/mongodb/clink.gif differ
diff --git a/slides/mongodb/clinked-0.png b/slides/mongodb/clinked-0.png
new file mode 100644
index 0000000..7cc04ec
Binary files /dev/null and b/slides/mongodb/clinked-0.png differ
diff --git a/slides/mongodb/clinked-1.png b/slides/mongodb/clinked-1.png
new file mode 100644
index 0000000..c9b43e5
Binary files /dev/null and b/slides/mongodb/clinked-1.png differ
diff --git a/slides/mongodb/clinks.xml b/slides/mongodb/clinks.xml
new file mode 100644
index 0000000..87fecab
--- /dev/null
+++ b/slides/mongodb/clinks.xml
@@ -0,0 +1,43 @@
+<slide>
+<title>Embedding Clinks</title>
+
+<image filename="clink.gif"/>
+
+<div effect="fade-out">
+<example><![CDATA[
+{
+ "_id" : ObjectId("569ec058b8c96e09421b29f4"),
+ "created_at" : 1453244504,
+ "user" : "Derick Rethans",
+ "user_slug" : "derick-rethans",
+ "whisky" : "Ord 10",
+ "whisky_slug" : "glen-ord-10-cadenheads",
+ "distillery" : "Glen Ord",
+ "distillery_slug" : "glen-ord",
+ "clinked_by" : [
+ ]
+}
+]]></example>
+</div>
+
+<div effect="fade-in">
+<example inline="1"><![CDATA[
+{
+ "_id" : ObjectId("569ec058b8c96e09421b29f4"),
+ "created_at" : 1453244504,
+ "user" : "Derick Rethans",
+ "user_slug" : "derick-rethans",
+ "whisky" : "Ord 10",
+ "whisky_slug" : "glen-ord-10-cadenheads",
+ "distillery" : "Glen Ord",
+ "distillery_slug" : "glen-ord",
+ "clinked_by" : [
+ *{*
+ *"slug" : "derick-rethans",*
+ *"name" : "Derick Rethans"*
+ *}*
+ ]
+}
+]]></example>
+</div>
+</slide>
diff --git a/slides/mongodb/clinks1.xml b/slides/mongodb/clinks1.xml
new file mode 100644
index 0000000..fa72b78
--- /dev/null
+++ b/slides/mongodb/clinks1.xml
@@ -0,0 +1,28 @@
+<slide>
+<title>Embedding Clinks (try 1)</title>
+
+<example inline="1"><![CDATA[
+{
+ "_id" : ObjectId("569ec058b8c96e09421b29f4"),
+ "clinked_by" : [ *{* *"slug" : "derick-rethans", "name" : "Derick Rethans"* *}* ]
+
+}
+]]></example>
+
+<blurb>See whether user has toasted:<example>
+$q = new Query( [ '_id' => new ObjectID( $checkin_id ), 'clinked_by.slug' => $slug );
+$res = iterator_to_array( $manager->executeQuery( 'dramio.checkins', $q ) );
+return count( $res[0] ) > 0;
+</example></blurb>
+
+<blurb>Add Clink:<example inline="1">
+$q = [ '_id' => new ObjectID( $checkin_id ), 'clinked_by.slug' => $slug ];
+$spec = [ *'$addToSet'* => [
+ 'clinked_by' => [ 'slug' => $user->slug, 'name' => $user->fullname ]
+] ];
+$bw = new BulkWrite;
+$bw->update( $q, $spec );
+$manager->executeBulkWrite( $bw );
+</example></blurb>
+
+</slide>
diff --git a/slides/mongodb/clinks2.xml b/slides/mongodb/clinks2.xml
new file mode 100644
index 0000000..5e3f8dd
--- /dev/null
+++ b/slides/mongodb/clinks2.xml
@@ -0,0 +1,28 @@
+<slide>
+<title>Embedding Clinks (try 1)</title>
+
+<example inline="1"><![CDATA[
+{
+ "_id" : ObjectId("569ec058b8c96e09421b29f4"),
+ "clinked_by" : [ *{* *"slug" : "derick-rethans", "name" : "Derick Rethans"* *}* ]
+
+}
+]]></example>
+
+<blurb>See whether user has toasted:<example>
+$q = new Query( [ '_id' => new ObjectID( $checkin_id ), 'clinked_by.slug' => $slug );
+$res = iterator_to_array( $manager->executeQuery( 'dramio.checkins', $q ) );
+return count( $res[0] ) > 0;
+</example></blurb>
+
+<blurb>Remove Clink:<example inline="1">
+$q = [ '_id' => new ObjectID( $checkin_id ), 'clinked_by.slug' => $slug ];
+$spec = [ *'$pull'* => [
+ 'clinked_by' => [ 'slug' => $user->slug, 'name' => $user->fullname ]
+] ];
+$bw = new BulkWrite;
+$bw->update( $q, $spec );
+$manager->executeBulkWrite( $bw );
+</example></blurb>
+
+</slide>
diff --git a/slides/mongodb/clinks3.xml b/slides/mongodb/clinks3.xml
new file mode 100644
index 0000000..77b61c1
--- /dev/null
+++ b/slides/mongodb/clinks3.xml
@@ -0,0 +1,18 @@
+<slide>
+<title>Embedding Clinks (try 2)</title>
+
+<example inline="1"><![CDATA[
+{
+ "_id" : ObjectId("569ec058b8c96e09421b29f4"),
+ "clinked_by" : [ *{ "slug" : "derick-rethans", "name" : "Derick Rethans" }* ]
+ *"clinked_count" : { "derick-rethans" : 1 }*
+}
+]]></example>
+
+<blurb>See whether user has toasted:<example inline="1">
+$q = new Query( [ '_id' => new ObjectID( $checkin_id ), 'clinked_by.slug' => $slug );
+$res = iterator_to_array( $manager->executeQuery( 'dramio.checkins', $q ) );
+return *(($res[0]->clinked_count->{$res[0]->user_slug} % 2) == 1);*
+</example></blurb>
+
+</slide>
diff --git a/slides/mongodb/clinks4.xml b/slides/mongodb/clinks4.xml
new file mode 100644
index 0000000..f0d2be7
--- /dev/null
+++ b/slides/mongodb/clinks4.xml
@@ -0,0 +1,28 @@
+<slide>
+<title>Embedding Clinks (try 2)</title>
+
+<blurb>Add/Remove Clink:<example inline="1">
+$cmd = new \MongoDB\Driver\Command( [
+ 'findAndModify' => 'checkins',
+ 'query' => [ '_id' => new \MongoDB\BSON\ObjectID( $this->_id ) ],
+ 'update' => [
+ *'$addToSet'* => [
+ "clinked_by" => [ 'slug' => $user->slug, 'name' => $user->fullname ]
+ ],
+ *'$inc' => [ "clinked_count.{$user_slug}" => 1 ]*
+ ],
+ *'new' => true,*
+] );
+
+$cursor = $manager->executeCommand( 'dramio', $cmd );
+*$cursor->setTypeMap(* [ 'document' => '\Dram\Checkin' ] );
+$result = $cursor->toArray()[0];
+
+return [
+ 'newCheckin' => $result->value,
+ *'toastedNew' => $result->value->clinked_count->{$user->slug} == 1,*
+ *'toasted' => ($result->value->clinked_count->{$user->slug} % 2) == 1*
+];
+</example></blurb>
+
+</slide>
diff --git a/slides/mongodb/clinks5.xml b/slides/mongodb/clinks5.xml
new file mode 100644
index 0000000..d43a853
--- /dev/null
+++ b/slides/mongodb/clinks5.xml
@@ -0,0 +1,21 @@
+<slide>
+<title>Embedding Clinks</title>
+
+<example inline="1"><![CDATA[
+{
+ "_id" : ObjectId("569ec058b8c96e09421b29f4"),
+ "clinked_by" : [ *{* *"slug" : "derick-rethans", "name" : "Derick Rethans"* *}* ]
+}
+]]></example>
+<blurb>*Con:* Not atomic<br/>*Pro:* Simple queries for status and update</blurb>
+<break lines="1"/>
+<example inline="1"><![CDATA[
+{
+ "_id" : ObjectId("569ec058b8c96e09421b29f4"),
+ "clinked_by" : [ *{ "slug" : "derick-rethans", "name" : "Derick Rethans" }* ]
+ *"clinked_count" : { "derick-rethans" : 13 }*
+}
+]]></example>
+<blurb>*Con:* More complex update queries<br/>*Pro:* Atomic; One *command* for update and getting state</blurb>
+
+</slide>
diff --git a/slides/mongodb/collection.jpg b/slides/mongodb/collection.jpg
new file mode 100644
index 0000000..11fdc96
Binary files /dev/null and b/slides/mongodb/collection.jpg differ
diff --git a/slides/mongodb/collections-title.xml b/slides/mongodb/collections-title.xml
new file mode 100644
index 0000000..f123434
--- /dev/null
+++ b/slides/mongodb/collections-title.xml
@@ -0,0 +1,4 @@
+<slide style="title">
+<title>Collections</title>
+<image align="center" filename="collection.jpg" attr="Flickr by Ana_Cotta at http://flickr.com/photos/9092428@N04/2510567032"/>
+</slide>
diff --git a/slides/mongodb/collections.xml b/slides/mongodb/collections.xml
new file mode 100644
index 0000000..2607ae7
--- /dev/null
+++ b/slides/mongodb/collections.xml
@@ -0,0 +1,85 @@
+<slide>
+<title>Collections</title>
+
+<div effect="fade-out">
+<example>
+{
+ "_id" : ObjectId("56b4f6dfb8c96e5c2e5121c7"),
+ "slug" : "ancnoc",
+ "name" : "anCnoc",
+ "region_slug" : "scotland-highlands",
+ "region" : "Scotland, Highlands",
+ "url" : "http://ancnoc.com/",
+}
+{
+ "_id" : ObjectId("56a6a6dab8c96e35ea7b3e24"),
+ "slug" : "suntory",
+ "name" : "Suntory",
+ "region_slug" : "japan",
+ "region" : "Japan",
+ "location" : "Osaka, Japan",
+ "description" : "Suntory Holdings Limited (サントリーホールディングス株式会社
+Santorī Hōrudingusu Kabushiki-Gaisha?) is a Japanese brewing and distilling
+company group. Established in 1899, it is one of the oldest companies in the
+distribution of alcoholic beverages in Japan, and makes Japanese whisky."
+}
+</example>
+</div>
+
+<div effect="fade-in-out">
+<example inline="1">
+{
+ *"_id" : ObjectId("56b4f6dfb8c96e5c2e5121c7"),*
+ *"slug" : "ancnoc",*
+ *"name" : "anCnoc",*
+ *"region_slug" : "scotland-highlands",*
+ *"region" : "Scotland, Highlands",*
+ "url" : "http://ancnoc.com/",
+}
+{
+ *"_id" : ObjectId("56a6a6dab8c96e35ea7b3e24"),*
+ *"slug" : "suntory",*
+ *"name" : "Suntory",*
+ *"region_slug" : "japan",*
+ *"region" : "Japan",*
+ "location" : "Osaka, Japan",
+ "description" : "Suntory Holdings Limited (サントリーホールディングス株式会社
+Santorī Hōrudingusu Kabushiki-Gaisha?) is a Japanese brewing and distilling
+company group. Established in 1899, it is one of the oldest companies in the
+distribution of alcoholic beverages in Japan, and makes Japanese whisky."
+}
+</example>
+<list>
+<bullet>Common fields</bullet>
+</list>
+</div>
+
+<div effect="fade-in stop">
+<example inline="1">
+{
+ "_id" : ObjectId("56b4f6dfb8c96e5c2e5121c7"),
+ "slug" : "ancnoc",
+ "name" : "anCnoc",
+ "region_slug" : "scotland-highlands",
+ "region" : "Scotland, Highlands",
+ *"url" : "http://ancnoc.com/",*
+}
+{
+ "_id" : ObjectId("56a6a6dab8c96e35ea7b3e24"),
+ "slug" : "suntory",
+ "name" : "Suntory",
+ "region_slug" : "japan",
+ "region" : "Japan",
+ *"location" : "Osaka, Japan",*
+ *"description" : "Suntory Holdings Limited (サントリーホールディングス株式会社*
+*Santorī Hōrudingusu Kabushiki-Gaisha?) is a Japanese brewing and distilling*
+*company group. Established in 1899, it is one of the oldest companies in the*
+*distribution of alcoholic beverages in Japan, and makes Japanese whisky."*
+}
+</example>
+<list>
+<bullet>Common fields</bullet>
+<bullet>Disparate fields</bullet>
+</list>
+</div>
+</slide>
diff --git a/slides/mongodb/considerations.xml b/slides/mongodb/considerations.xml
index 6fac735..f4995b2 100644
--- a/slides/mongodb/considerations.xml
+++ b/slides/mongodb/considerations.xml
@@ -1,17 +1,13 @@
-<slide>
-<title>Schema considerations</title>
-
+<slide style="imagebg">
+<title>Schema Considerations</title>
+<image align="center" filename="keys.jpg"/>
+<break lines="10"/>
+<div class="center-blurb-wide">
<list>
<blurb>Access Patterns</blurb>
<bullet>Read / Write Ratio</bullet>
<bullet>Types of queries and updates</bullet>
<bullet>Data life-cycle</bullet>
</list>
-<break/>
-<blurb>Considerations</blurb>
-<list>
- <bullet>Only single-document writes are atomic</bullet>
- <bullet>No joins (reference vs. embed)</bullet>
- <bullet>Growing documents may require relocation</bullet>
-</list>
+</div>
</slide>
diff --git a/slides/mongodb/data-model.xml b/slides/mongodb/data-model.xml
new file mode 100644
index 0000000..8a2916c
--- /dev/null
+++ b/slides/mongodb/data-model.xml
@@ -0,0 +1,20 @@
+<slide style="imagebg">
+<title>Data Model</title>
+<image align="center" filename="keys.jpg"/>
+<break lines="6"/>
+<div class="center-blurb-wide">
+<list>
+ <bullet>No relations between collections</bullet>
+ <bullet>No foreign keys</bullet>
+ <bullet>No transactions</bullet>
+</list>
+</div>
+<break lines="2"/>
+<div class="center-blurb-wide">
+<list>
+ <bullet>Use nested documents and arrays</bullet>
+ <bullet>Duplicate data</bullet>
+ <bullet>Use atomic operations</bullet>
+</list>
+</div>
+</slide>
diff --git a/slides/mongodb/document-complex.xml b/slides/mongodb/document-complex.xml
new file mode 100644
index 0000000..7e1f0ae
--- /dev/null
+++ b/slides/mongodb/document-complex.xml
@@ -0,0 +1,79 @@
+<slide>
+<title>Documents: Complex</title>
+
+<div effect="fade-out">
+<example>
+{
+ "_id" : "derick@localhost",
+ "fullname" : "Derick Rethans",
+ "slug" : "derick-rethans",
+ "created_at" : 1452546141,
+ "timezone" : "Europe/London",
+ "confirmed" : true,
+ "confirmed_at" : 1452546148,
+ "location" : "London, UK",
+ "words" : [ "derick", "rethans", "london", "uk" ],
+ "count" : 16,
+ "count_unique" : 13,
+ "badges" : [
+ { n: "unique1", l: 1 },
+ { n: "age21", l: 3 }
+ ],
+ "isAdmin" : true
+}
+</example>
+</div>
+
+<div effect="fade-in-out">
+<example inline="1">
+{
+ |ff0000|*"_id" : "derick@localhost",*|
+ "fullname" : "Derick Rethans",
+ "slug" : "derick-rethans",
+ "created_at" : 1452546141,
+ "timezone" : "Europe/London",
+ "confirmed" : true,
+ "confirmed_at" : 1452546148,
+ "location" : "London, UK",
+ "words" : [ "derick", "rethans", "london", "uk" ],
+ "count" : 16,
+ "count_unique" : 13,
+ "badges" : [
+ { n: "unique1", l: 1 },
+ { n: "age21", l: 3 }
+ ],
+ "isAdmin" : true
+}
+</example>
+<list>
+<bullet>%_id%: does not have to be an Object ID</bullet>
+</list>
+</div>
+
+<div effect="fade-in stop">
+<example inline="1">
+{
+ |ff0000|*"_id" : "derick@localhost",*|
+ "fullname" : "Derick Rethans",
+ "slug" : "derick-rethans",
+ "created_at" : 1452546141,
+ "timezone" : "Europe/London",
+ "confirmed" : true,
+ "confirmed_at" : 1452546148,
+ "location" : "London, UK",
+ |ff0000|*"words" : [ "derick", "rethans", "london", "uk" ],*|
+ "count" : 16,
+ "count_unique" : 13,
+ |ff0000|*"badges" : [*|
+ |ff0000|*{ n: "unique1", l: 1 },*|
+ |ff0000|*{ n: "age21", l: 3 }*|
+ |ff0000|*],*|
+ "isAdmin" : true
+}
+</example>
+<list>
+<bullet>%_id%: does not have to be an Object ID</bullet>
+<bullet>Values can be arrays, documents, or arrays of documents</bullet>
+</list>
+</div>
+</slide>
diff --git a/slides/mongodb/document-simple.xml b/slides/mongodb/document-simple.xml
index d9e8ba4..f808d6f 100644
--- a/slides/mongodb/document-simple.xml
+++ b/slides/mongodb/document-simple.xml
@@ -1,38 +1,73 @@
<slide>
-<title>Documents</title>
-
-<list>
- <bullet>Are *schemaless*</bullet>
- <bullet>Can have embedded documents</bullet>
-</list>
-<break/>
+<title>Documents: Simple</title>
<div effect="fade-out">
-<blurb>Simple document:</blurb>
<example>
{
- "_id" : ObjectId("4cb4ab6d7addf98506010001"),
- "twitter" : "derickr",
- "name" : "Derick Rethans"
+ "_id" : ObjectId("569c19f3b8c96e09421b2926"),
+ "slug" : "ardbeg",
+ "name" : "Ardbeg",
+ "created_at" : 1453070835,
+ "region_slug" : "scotland-islay",
+ "region" : "Scotland, Islay",
+ "location" : "Ardbeg, Scotland, UK",
+ "closed" : false,
+ "description" : "Ardbeg Distillery (Scottish Gaelic: Taigh-stail Àirde Beaga)
+is a Scotch whisky distillery in Ardbeg on the south coast of the isle of
+Islay, Argyll and Bute, Scotland, in the Inner Hebrides group of islands. The
+distillery is owned by Louis Vuitton Moët Hennessy, and produces a heavily
+peated Islay whisky.[2] The distillery uses malted barley sourced from the
+maltings in Port Ellen. (Wikipedia)"
}
</example>
</div>
-<div effect="fade-in">
-<blurb>Document with embedded documents:</blurb>
-<example>
+<div effect="fade-in-out">
+<example inline="1">
{
- "_id" : "derickr",
- "name" : "Derick Rethans",
- "bookmarks" : [
- { "title" : "MongoDB",
- "url" : "http://mongodb.org",
- },
- { "title" : "10gen",
- "url" : "http://10gen.com",
- }
- ]
+ |ff0000|*"_id" : ObjectId("569c19f3b8c96e09421b2926"),*|
+ "slug" : "ardbeg",
+ "name" : "Ardbeg",
+ "created_at" : 1453070835,
+ "region_slug" : "scotland-islay",
+ "region" : "Scotland, Islay",
+ "location" : "Ardbeg, Scotland, UK",
+ "closed" : false,
+ "description" : "Ardbeg Distillery (Scottish Gaelic: Taigh-stail Àirde Beaga)
+is a Scotch whisky distillery in Ardbeg on the south coast of the isle of
+Islay, Argyll and Bute, Scotland, in the Inner Hebrides group of islands. The
+distillery is owned by Louis Vuitton Moët Hennessy, and produces a heavily
+peated Islay whisky.[2] The distillery uses malted barley sourced from the
+maltings in Port Ellen. (Wikipedia)"
}
</example>
+<list>
+<bullet>%_id%: immutable unique key of document</bullet>
+</list>
+</div>
+
+<div effect="fade-in stop">
+<example inline="1">
+{
+ |ff0000|*"_id" : ObjectId("569c19f3b8c96e09421b2926"),*|
+ "slug" : "ardbeg",
+ "name" : "Ardbeg",
+ "created_at" : 1453070835,
+ "region_slug" : "scotland-islay",
+ "region" : "Scotland, Islay",
+ "location" : "Ardbeg, Scotland, UK",
+ "closed" : false,
+ "description" : "Ardbeg Distillery (Scottish Gaelic: Taigh-stail |ff0000|*À*|irde Beaga)
+is a Scotch whisky distillery in Ardbeg on the south coast of the isle of
+Islay, Argyll and Bute, Scotland, in the Inner Hebrides group of islands. The
+distillery is owned by Louis Vuitton Mo|ff0000|*ë*|t Hennessy, and produces a heavily
+peated Islay whisky.[2] The distillery uses malted barley sourced from the
+maltings in Port Ellen. (Wikipedia)"
+}
+</example>
+<list>
+<bullet>%_id%: immutable unique key of document</bullet>
+<bullet>All strings are UTF-8</bullet>
+</list>
</div>
</slide>
diff --git a/slides/mongodb/document-title.xml b/slides/mongodb/document-title.xml
new file mode 100644
index 0000000..0073bcd
--- /dev/null
+++ b/slides/mongodb/document-title.xml
@@ -0,0 +1,4 @@
+<slide style="title">
+<title>Documents</title>
+<image align="center" filename="document.jpg" attr="Photographs taken by Charles C. Pierce"/>
+</slide>
diff --git a/slides/mongodb/document.jpg b/slides/mongodb/document.jpg
new file mode 100644
index 0000000..9660931
Binary files /dev/null and b/slides/mongodb/document.jpg differ
diff --git a/slides/mongodb/dram-erd-in-mongo.xml b/slides/mongodb/dram-erd-in-mongo.xml
new file mode 100644
index 0000000..e4d9cf0
--- /dev/null
+++ b/slides/mongodb/dram-erd-in-mongo.xml
@@ -0,0 +1,5 @@
+<slide>
+<title>Dram.IO ERD (MongoDB)</title>
+
+<image filename="dram.io.mongo2.png"/>
+</slide>
diff --git a/slides/mongodb/dram-erd.xml b/slides/mongodb/dram-erd.xml
new file mode 100644
index 0000000..56357b9
--- /dev/null
+++ b/slides/mongodb/dram-erd.xml
@@ -0,0 +1,5 @@
+<slide>
+<title>Dram.IO ERD</title>
+
+<image filename="dram.io.png"/>
+</slide>
diff --git a/slides/mongodb/dram.io.mongo2.png b/slides/mongodb/dram.io.mongo2.png
new file mode 100644
index 0000000..bdbc691
Binary files /dev/null and b/slides/mongodb/dram.io.mongo2.png differ
diff --git a/slides/mongodb/dram.io.png b/slides/mongodb/dram.io.png
new file mode 100644
index 0000000..434193d
Binary files /dev/null and b/slides/mongodb/dram.io.png differ
diff --git a/slides/mongodb/embed-vs-link.xml b/slides/mongodb/embed-vs-link.xml
index 266bfe9..12528d9 100644
--- a/slides/mongodb/embed-vs-link.xml
+++ b/slides/mongodb/embed-vs-link.xml
@@ -1,17 +1,23 @@
-<slide>
+<slide style="imagebg">
<title>Embedding versus Linking</title>
+<image align="center" filename="keys.jpg"/>
+<break lines="5"/>
+<div class="center-blurb-wide">
<blurb>Embedding</blurb>
<list>
- <bullet>Simple data structure</bullet>
- <bullet>How often do you update?</bullet>
+ <bullet>Simpler data structure</bullet>
+ <bullet>What do you read often together?</bullet>
<bullet>Will the document grow and grow?</bullet>
</list>
-
+</div>
+<break lines="1"/>
+<div class="center-blurb-wide">
<blurb>Linking</blurb>
<list>
<bullet>More complex data structure</bullet>
- <bullet>Unlimited data size</bullet>
<bullet>More, smaller documents</bullet>
+ <bullet>Unlimited data size</bullet>
</list>
+</div>
</slide>
diff --git a/slides/mongodb/index-title.xml b/slides/mongodb/index-title.xml
new file mode 100644
index 0000000..08065fb
--- /dev/null
+++ b/slides/mongodb/index-title.xml
@@ -0,0 +1,4 @@
+<slide style="title">
+<title>Indexes</title>
+<image align="center" filename="indexes.jpg" attr="Flickr by David Fulmer at https://www.flickr.com/photos/annarbor/4350629792"/>
+</slide>
diff --git a/slides/mongodb/index.xml b/slides/mongodb/index.xml
new file mode 100644
index 0000000..4143d17
--- /dev/null
+++ b/slides/mongodb/index.xml
@@ -0,0 +1,127 @@
+<slide>
+<title>Indexes</title>
+
+<div effect="fade-out">
+<example>
+{
+ "_id" : ObjectId("56a7f861b8c96e06585e8195"),
+ "name" : "Glen Grant-Glenlivet 20",
+ "style" : "Single Cask",
+ "style_slug" : "single-cask",
+ "description" : "Distilled in 1995 and bottled in October 2005.",
+ "attributes": {
+ "age" : 20,
+ "cask_strength" : true,
+ },
+ "words" : [ "glen", "grant", "glenlivet", "20", "cadenheads" ],
+}
+</example>
+</div>
+
+<div effect="fade-in-out">
+<example inline="1">
+{
+ *"_id"* : ObjectId("56a7f861b8c96e06585e8195"),
+ "name" : "Glen Grant-Glenlivet 20",
+ "style" : "Single Cask",
+ "style_slug" : "single-cask",
+ "description" : "Distilled in 1995 and bottled in October 2005.",
+ "attributes": {
+ "age" : 20,
+ "cask_strength" : true,
+ },
+ "words" : [ "glen", "grant", "glenlivet", "20", "cadenheads" ],
+}
+</example>
+<list>
+<bullet>%_id%: automatic unique key</bullet>
+</list>
+</div>
+
+<div effect="fade-in-out">
+<example inline="1">
+{
+ "_id" : ObjectId("56a7f861b8c96e06585e8195"),
+ *"name" : "Glen Grant-Glenlivet 20",*
+ "style_slug" : "single-cask",
+ "description" : "Distilled in 1995 and bottled in October 2005.",
+ "attributes": {
+ "age" : 20,
+ "cask_strength" : true,
+ },
+ "words" : [ "glen", "grant", "glenlivet", "20", "cadenheads" ],
+}
+</example>
+<list>
+<bullet>%_id%: automatic unique key</bullet>
+<bullet>%name%: unique key</bullet>
+</list>
+</div>
+
+<div effect="fade-in-out">
+<example inline="1">
+{
+ "_id" : ObjectId("56a7f861b8c96e06585e8195"),
+ "name" : "Glen Grant-Glenlivet 20",
+ *"style_slug" : "single-cask",*
+ "description" : "Distilled in 1995 and bottled in October 2005.",
+ "attributes": {
+ "age" : 20,
+ "cask_strength" : true,
+ },
+ "words" : [ "glen", "grant", "glenlivet", "20", "cadenheads" ],
+}
+</example>
+<list>
+<bullet>%_id%: automatic unique key</bullet>
+<bullet>%name%: unique key</bullet>
+<bullet>%style_slug%: category lookups</bullet>
+</list>
+</div>
+
+<div effect="fade-in-out">
+<example inline="1">
+{
+ "_id" : ObjectId("56a7f861b8c96e06585e8195"),
+ "name" : "Glen Grant-Glenlivet 20",
+ "style_slug" : "single-cask",
+ "description" : "Distilled in 1995 and bottled in October 2005.",
+ *"attributes": {*
+ *"age" : 20,*
+ "cask_strength" : true,
+ },
+ "words" : [ "glen", "grant", "glenlivet", "20", "cadenheads" ],
+}
+</example>
+<list>
+<bullet>%_id%: automatic unique key</bullet>
+<bullet>%name%: unique key</bullet>
+<bullet>%style_slug%: category lookups</bullet>
+<bullet>%attributes.age%: on nested fields</bullet>
+</list>
+</div>
+
+<div effect="fade-in-out">
+<example inline="1">
+{
+ "_id" : ObjectId("56a7f861b8c96e06585e8195"),
+ "name" : "Glen Grant-Glenlivet 20",
+ "style_slug" : "single-cask",
+ "description" : "Distilled in 1995 and bottled in October 2005.",
+ "attributes": {
+ "age" : 20,
+ "cask_strength" : true,
+ },
+ *"words" : [ "glen", "grant", "glenlivet", "20", "cadenheads" ],*
+}
+</example>
+<list>
+<bullet>%_id%: automatic unique key</bullet>
+<bullet>%name%: unique key</bullet>
+<bullet>%style_slug%: category lookups</bullet>
+<bullet>%attributes.age%: on nested fields</bullet>
+<bullet>%words%: on array values</bullet>
+</list>
+</div>
+
+</slide>
diff --git a/slides/mongodb/indexes-explain.xml b/slides/mongodb/indexes-explain.xml
new file mode 100644
index 0000000..4681368
--- /dev/null
+++ b/slides/mongodb/indexes-explain.xml
@@ -0,0 +1,23 @@
+<slide>
+<title>Explain (No Index)</title>
+
+<example inline="1"><![CDATA[
+> db.whisky.find( { distillery: 'Ord' } ).explain();
+{
+ "queryPlanner" : {
+ "namespace" : *"dramio.whisky",*
+ "indexFilterSet" : false,
+ "parsedQuery" : { "distillery" : { "$eq" : "Ord" } },
+ "winningPlan" : {
+ "stage" : *"COLLSCAN",*
+ "filter" : {
+ "distillery" : {
+ *"$eq" : "Ord"*
+ }
+ },
+ "direction" : "forward"
+ },
+ },
+}
+]]></example>
+</slide>
diff --git a/slides/mongodb/indexes-explain2.xml b/slides/mongodb/indexes-explain2.xml
new file mode 100644
index 0000000..0bb6d47
--- /dev/null
+++ b/slides/mongodb/indexes-explain2.xml
@@ -0,0 +1,31 @@
+<slide>
+<title>Explain (Index)</title>
+
+<example inline="1"><![CDATA[
+> db.whisky.find( { name: 'Ord 10' } ).explain();
+{
+ "queryPlanner" : {
+ "namespace" : "dramio.whisky",
+ "indexFilterSet" : false,
+ "parsedQuery" : { "name" : { "$eq" : "Ord 10" } },
+ "winningPlan" : {
+ *"stage" : "FETCH",*
+ "inputStage" : {
+ *"stage" : "IXSCAN",*
+ "keyPattern" : {
+ "name" : 1
+ },
+ "indexName" : "name_1",
+ *"isMultiKey"* : false,
+ "direction" : *"forward"*,
+ "indexBounds" : {
+ "name" : [
+ "[\"Ord 10\", \"Ord 10\"]"
+ ]
+ }
+ }
+ },
+ },
+}
+]]></example>
+</slide>
diff --git a/slides/mongodb/indexes-explain3.xml b/slides/mongodb/indexes-explain3.xml
new file mode 100644
index 0000000..db573f1
--- /dev/null
+++ b/slides/mongodb/indexes-explain3.xml
@@ -0,0 +1,32 @@
+<slide>
+<title>Explain (Covering Index)</title>
+
+<example inline="1"><![CDATA[
+> db.whisky.find( { name: 'Ord 10' }, { _id: 0, name: 1 } ).explain();
+{
+ "queryPlanner" : {
+ "namespace" : "dramio.whisky",
+ "indexFilterSet" : false,
+ "parsedQuery" : { "name" : { "$eq" : "Ord 10" } },
+ "winningPlan" : {
+ *"stage" : "PROJECTION",*
+ "transformBy" : *{ "_id" : 0, "name" : 1 }*,
+ "inputStage" : {
+ *"stage" : "IXSCAN",*
+ "keyPattern" : {
+ "name" : 1
+ },
+ "indexName" : "name_1",
+ "isMultiKey" : false,
+ "direction" : "forward",
+ "indexBounds" : {
+ "name" : [
+ "[\"Ord 10\", \"Ord 10\"]"
+ ]
+ }
+ }
+ },
+ },
+}
+]]></example>
+</slide>
diff --git a/slides/mongodb/indexes-new.xml b/slides/mongodb/indexes-new.xml
new file mode 100644
index 0000000..82f4c9c
--- /dev/null
+++ b/slides/mongodb/indexes-new.xml
@@ -0,0 +1,15 @@
+<slide style="imagebg">
+<title>Indexes</title>
+
+<image align="center" filename="index.jpg"/>
+<break lines="5"/>
+<div class="center-blurb-wide">
+<list>
+ <bullet>Indexes are just as important as in a relational database</bullet>
+ <bullet>Every collection has (automatically) an index on %_id%</bullet>
+ <bullet>Indexes can be: single field, compound key, on nested field names</bullet>
+ <bullet>MongoCursor->explain().</bullet>
+</list>
+</div>
+</slide>
+
diff --git a/slides/mongodb/indexes-php.xml b/slides/mongodb/indexes-php.xml
new file mode 100644
index 0000000..6966cf1
--- /dev/null
+++ b/slides/mongodb/indexes-php.xml
@@ -0,0 +1,30 @@
+<slide>
+<title>Creating Indexes</title>
+
+<blurb>Shell</blurb>
+<example>
+db.checkins.createIndex( { 'clinked_by.slug': 1 } );
+</example>
+
+<blurb>Driver</blurb>
+<example inline="1"><![CDATA[
+$cmd = new \MongoDB\Driver\Command( [
+ 'createIndexes => 'checkins',
+ 'indexes' => [
+ [ *'key'* => [ 'user_slug' => 1, 'friend_slug => 1 ], *'unique'* => true ],
+ ]
+] );
+$manager->executeCommand( $cmd );
+]]></example>
+
+<blurb>Library</blurb>
+<example inline="1"><![CDATA[
+require 'vendor/autoload.php';
+$collection = (new MongoDB\Client)->dramio->user;
+$collection->createIndex(
+ [ 'validation_code' => 1 ],
+ *[ 'sparse' => true ]*
+);
+]]></example>
+
+</slide>
diff --git a/slides/mongodb/indexes-special.xml b/slides/mongodb/indexes-special.xml
new file mode 100644
index 0000000..83467da
--- /dev/null
+++ b/slides/mongodb/indexes-special.xml
@@ -0,0 +1,25 @@
+<slide style="imagebg">
+<title>Special Indexes</title>
+
+<image align="center" filename="index.jpg"/>
+<break lines="5"/>
+<div class="center-blurb-wide">
+<blurb>Geospatial Indexes (2d, and 2dsphere)</blurb>
+<list>
+ <bullet>Find objects near a pair of coordinates</bullet>
+ <bullet>Find objects intersecting other objects</bullet>
+ <bullet>GeoJSON: Point, Line, Polygon, GeometryCollection</bullet>
+</list>
+</div>
+
+<break/>
+
+<div class="center-blurb-wide">
+<blurb>Text Indexes</blurb>
+<list>
+ <bullet>"Full Text Search"</bullet>
+ <bullet>Stemming, Weighing, Ranking</bullet>
+</list>
+</div>
+</slide>
+
diff --git a/slides/mongodb/indexes-title.xml b/slides/mongodb/indexes-title.xml
new file mode 100644
index 0000000..3fa0f4f
--- /dev/null
+++ b/slides/mongodb/indexes-title.xml
@@ -0,0 +1,4 @@
+<slide style="title">
+<title>Indexes</title>
+<image align="center" filename="index.jpg"/>
+</slide>
diff --git a/slides/mongodb/indexes.jpg b/slides/mongodb/indexes.jpg
new file mode 100644
index 0000000..b455302
Binary files /dev/null and b/slides/mongodb/indexes.jpg differ
diff --git a/slides/mongodb/keys-title.xml b/slides/mongodb/keys-title.xml
new file mode 100644
index 0000000..5407a31
--- /dev/null
+++ b/slides/mongodb/keys-title.xml
@@ -0,0 +1,4 @@
+<slide style="title">
+<title>Data Model</title>
+<image align="center" filename="keys.jpg"/>
+</slide>
diff --git a/slides/mongodb/keys.jpg b/slides/mongodb/keys.jpg
new file mode 100644
index 0000000..6be1b89
Binary files /dev/null and b/slides/mongodb/keys.jpg differ
diff --git a/slides/mongodb/phplib-crud.xml b/slides/mongodb/phplib-crud.xml
new file mode 100644
index 0000000..ea388fb
--- /dev/null
+++ b/slides/mongodb/phplib-crud.xml
@@ -0,0 +1,30 @@
+<slide>
+<title>MongoDB & PHP: CRUD</title>
+
+<example><![CDATA[<?php
+require 'vendor/autoload.php';
+
+$whiskies = (new MongoDB\Client)->dramio->whisky;
+
+// Find one document:
+$whisky = $whiskies->findOne( [ 'name' => 'Cambus 26' ] );
+
+// Find multiple documents:
+$cursor = $whiskies->find( [ 'style' => 'single-cask' ] );
+
+// Insert one document:
+$whiskies->insertOne( [ 'name' => 'Glenfiddich 15' ] );
+
+// Insert multiple documents:
+$whiskies->insertMany( [
+ [ 'name' => 'Glenlivet 12' ],
+ [ 'name' => 'Glenlivet 15' ]
+] );
+
+// Update document:
+$whiskies->updateOne( [ 'slug' => 'cambus-26' ], [ '$set' => [ 'age' => 26 ] ] );
+
+// Remove document:
+$whiskies->deleteOne( [ 'name' => 'Jack Daniels' ] );
+?>]]></example>
+</slide>
diff --git a/slides/mongodb/phplib-index.xml b/slides/mongodb/phplib-index.xml
new file mode 100644
index 0000000..6c69028
--- /dev/null
+++ b/slides/mongodb/phplib-index.xml
@@ -0,0 +1,21 @@
+<slide>
+<title>MongoDB & PHP: Indexes</title>
+
+<example><![CDATA[<?php
+require 'vendor/autoload.php';
+
+$whiskies = (new MongoDB\Client)->dramio->whisky;
+
+// Create normal index
+$whiskies->createIndex( [ 'distiller_slug' => 1 );
+
+// Create unique index
+$whiskies->createIndex( [ 'name' => 1 ], [ 'unique' => true ] );
+
+// Create nested index
+$whiskies->createIndex( [ 'attributes.age' => 1 ] );
+
+// Create compound index
+$whiskies->createIndex( [ 'brand' => 1', 'age' => 1 ] );
+?>]]></example>
+</slide>
diff --git a/slides/mongodb/phplib-intro.xml b/slides/mongodb/phplib-intro.xml
new file mode 100644
index 0000000..2fd31e7
--- /dev/null
+++ b/slides/mongodb/phplib-intro.xml
@@ -0,0 +1,27 @@
+<slide>
+<title>MongoDB & PHP</title>
+
+<list>
+ <bullet>Extension: %pecl/mongodb% (PHP 5.4 and higher)</bullet>
+ <bullet>Library: %phplib% (%mongodb/mongodb% on composer)</bullet>
+</list>
+
+<blurb>Installation:</blurb>
+<example>
+pecl install mongodb
+echo "extension=mongodb.so" > /etc/php5/cli/conf.d/20-mongodb.ini"
+
+mkdir new-project
+cd new-project
+composer require mongodb/mongodb
+</example>
+
+<blurb>In your script:</blurb>
+
+<example><![CDATA[<?php
+require 'vendor/autoload.php';
+
+$client = new \Mongo\Client;
+$collection = $client->selectCollection( 'databasename', 'collectionname' );
+?>]]></example>
+</slide>
diff --git a/slides/mongodb/phplib-title.xml b/slides/mongodb/phplib-title.xml
new file mode 100644
index 0000000..f9c2498
--- /dev/null
+++ b/slides/mongodb/phplib-title.xml
@@ -0,0 +1,4 @@
+<slide style="title">
+<title>PHP & MongoDB</title>
+<image align="center" filename="phplib.jpg" attr="Derick Rethans"/>
+</slide>
diff --git a/slides/mongodb/phplib.jpg b/slides/mongodb/phplib.jpg
new file mode 100644
index 0000000..375b087
Binary files /dev/null and b/slides/mongodb/phplib.jpg differ
diff --git a/slides/mongodb/queries.jpg b/slides/mongodb/queries.jpg
new file mode 100644
index 0000000..91a4b25
Binary files /dev/null and b/slides/mongodb/queries.jpg differ
diff --git a/slides/mongodb/questions.xml b/slides/mongodb/questions.xml
index db3b71f..940aa14 100644
--- a/slides/mongodb/questions.xml
+++ b/slides/mongodb/questions.xml
@@ -1,3 +1,4 @@
-<slide type="section">
-<blurb>Any questions?</blurb>
+<slide style="title">
+<title>Any Queries?</title>
+<image align="center" filename="queries.jpg" attr="Véronique Debord-Lazaro — https://www.flickr.com/photos/debord/4932655275"/>
</slide>
diff --git a/slides/mongodb/tip-array-key.xml b/slides/mongodb/tip-array-key.xml
index 25118da..a2ff1f7 100644
--- a/slides/mongodb/tip-array-key.xml
+++ b/slides/mongodb/tip-array-key.xml
@@ -1,5 +1,5 @@
<slide>
-<title>Tips and Hints: document keys</title>
+<title>Tip: document keys</title>
<blurb>Don't do:</blurb>
<example><![CDATA[temperature: {
diff --git a/slides/mongodb/tip-paged-result.xml b/slides/mongodb/tip-paged-result.xml
index 4e5fec3..9e70522 100644
--- a/slides/mongodb/tip-paged-result.xml
+++ b/slides/mongodb/tip-paged-result.xml
@@ -1,5 +1,5 @@
<slide>
-<title>Tips and hints: pre-page results</title>
+<title>Tip: pre-page results</title>
<example><![CDATA[article: { _id: 42, title: "Xdebug saves you time!" }]]></example>
diff --git a/slides/mongodb/whisky-checking.xml b/slides/mongodb/whisky-checking.xml
new file mode 100644
index 0000000..7c70d51
--- /dev/null
+++ b/slides/mongodb/whisky-checking.xml
@@ -0,0 +1,23 @@
+<slide>
+<title>Listing all Checkins</title>
+
+<table class="leftalign">
+<tr>
+<td><image filename="checkin2.png"/></td>
+<td align="left">
+<blurb>*Pro:* Quick to see all notes for a whisky</blurb>
+<blurb>*Con:*<br/>Difficult to see notes for user<br/>Document size limitations</blurb>
+</td>
+</tr>
+</table>
+<table class="leftalign">
+<tr>
+<td><image filename="checkin1.png"/></td>
+<td align="left">
+<blurb>*Pro:* Easy to see all notes for user *or* whisky</blurb>
+<blurb>*Con:* It takes two queries</blurb>
+</td>
+</tr>
+</table>
+
+</slide>
diff --git a/slides/mongodb/whisky-words.png b/slides/mongodb/whisky-words.png
new file mode 100644
index 0000000..a17d0af
Binary files /dev/null and b/slides/mongodb/whisky-words.png differ
diff --git a/slides/mongodb/whisky-words.xml b/slides/mongodb/whisky-words.xml
new file mode 100644
index 0000000..62fe643
--- /dev/null
+++ b/slides/mongodb/whisky-words.xml
@@ -0,0 +1,41 @@
+<slide>
+<title>Finding a Whisky by Words</title>
+
+<table class="leftalign">
+<tr>
+<td><image filename="whisky-words.png"/></td>
+<td align="left">
+<example>
+SELECT w.slug
+FROM whisky w
+LEFT JOIN whisky_words ww
+ ON (w._id = ww.whisky_id)
+WHERE ww.word = 'glenfiddich'
+</example>
+</td>
+</tr>
+</table>
+<table class="leftalign">
+<tr>
+<td>
+<example>
+name: "Glenfiddich 12",
+slug: "glenfiddich-12",
+words: [
+ "glenfiddich",
+ "12"
+],
+</example>
+</td>
+<td>
+<example>
+db.whisky.find(
+ { words: 'glenfiddich' },
+ { slug: 1 }
+).pretty();
+</example>
+</td>
+</tr>
+</table>
+
+</slide>
diff --git a/style-black.css b/style-black.css
new file mode 100644
index 0000000..4ff9584
--- /dev/null
+++ b/style-black.css
@@ -0,0 +1,4 @@
+body
+{
+ background-color: black;
+}
diff --git a/style-black.xml b/style-black.xml
new file mode 100644
index 0000000..4ff9584
--- /dev/null
+++ b/style-black.xml
@@ -0,0 +1,4 @@
+body
+{
+ background-color: black;
+}