From aeadb53375bfb7c247cc7523a3d78511a1470d89 Mon Sep 17 00:00:00 2001 From: Karl Seguin Date: Mon, 10 Oct 2011 23:15:25 +0800 Subject: [PATCH] fk_vs_ed --- .gitignore | 1 + _includes/fk_vs_ed/1.html | 1 + _includes/fk_vs_ed/10.html | 4 + _includes/fk_vs_ed/11.html | 6 ++ _includes/fk_vs_ed/12.html | 1 + _includes/fk_vs_ed/2.html | 20 +++++ _includes/fk_vs_ed/3.html | 5 ++ _includes/fk_vs_ed/4.html | 14 +++ _includes/fk_vs_ed/5.html | 15 ++++ _includes/fk_vs_ed/6.html | 3 + _includes/fk_vs_ed/7.html | 10 +++ _includes/fk_vs_ed/8.html | 6 ++ _includes/fk_vs_ed/9.html | 14 +++ _layouts/bare.html | 23 +++++ assets/css/main.css | 20 +++++ assets/i/leaf.png | Bin 0 -> 1504 bytes assets/js/main.js | 30 +++++++ assets/js/multi.js | 84 ++++++++++++++++++ .../index.html | 22 +++++ .../styles.css | 12 +++ index.html | 5 +- 21 files changed, 295 insertions(+), 1 deletion(-) create mode 100644 .gitignore create mode 100644 _includes/fk_vs_ed/1.html create mode 100644 _includes/fk_vs_ed/10.html create mode 100644 _includes/fk_vs_ed/11.html create mode 100644 _includes/fk_vs_ed/12.html create mode 100644 _includes/fk_vs_ed/2.html create mode 100644 _includes/fk_vs_ed/3.html create mode 100644 _includes/fk_vs_ed/4.html create mode 100644 _includes/fk_vs_ed/5.html create mode 100644 _includes/fk_vs_ed/6.html create mode 100644 _includes/fk_vs_ed/7.html create mode 100644 _includes/fk_vs_ed/8.html create mode 100644 _includes/fk_vs_ed/9.html create mode 100644 _layouts/bare.html create mode 100644 assets/css/main.css create mode 100644 assets/i/leaf.png create mode 100644 assets/js/main.js create mode 100644 assets/js/multi.js create mode 100644 foreign-keys-versus-embedded-documents/index.html create mode 100644 foreign-keys-versus-embedded-documents/styles.css diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ca35be0 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +_site diff --git a/_includes/fk_vs_ed/1.html b/_includes/fk_vs_ed/1.html new file mode 100644 index 0000000..4d5baf7 --- /dev/null +++ b/_includes/fk_vs_ed/1.html @@ -0,0 +1 @@ +
Inevitably, everyone who uses MongoDB comes to a choice between using multiple collections with id references or embedded documents
\ No newline at end of file diff --git a/_includes/fk_vs_ed/10.html b/_includes/fk_vs_ed/10.html new file mode 100644 index 0000000..cb12fa3 --- /dev/null +++ b/_includes/fk_vs_ed/10.html @@ -0,0 +1,4 @@ +
+

So, separate collections are good if you need to select individual documents, need more control over querying.

+

Embedded documents are good when you want the entire document, the document with a $slice of comments, or with no comments at all

+
\ No newline at end of file diff --git a/_includes/fk_vs_ed/11.html b/_includes/fk_vs_ed/11.html new file mode 100644 index 0000000..b547f8e --- /dev/null +++ b/_includes/fk_vs_ed/11.html @@ -0,0 +1,6 @@ +
+

As a general rule, if you have a lot of "comments" or if they are large, a separate collection might be best.

+

Smaller documents tend to be a natural fit for embedding

+
+ +
Virtual collection + positional field selection are relevant upcoming[ish] features
\ No newline at end of file diff --git a/_includes/fk_vs_ed/12.html b/_includes/fk_vs_ed/12.html new file mode 100644 index 0000000..61d5d21 --- /dev/null +++ b/_includes/fk_vs_ed/12.html @@ -0,0 +1 @@ +
Remember, you can always change your mind. Trying each out is the best way to learn.
\ No newline at end of file diff --git a/_includes/fk_vs_ed/2.html b/_includes/fk_vs_ed/2.html new file mode 100644 index 0000000..2e418a7 --- /dev/null +++ b/_includes/fk_vs_ed/2.html @@ -0,0 +1,20 @@ +

Use separate collections

+
+  > db.posts.find();
+  {_id: 1, title: 'unicorns are awesome', ...}
+
+  > db.comments.find();
+  {_id: 1, post_id: 1, title: 'i agree', ...}
+  {_id: 2, post_id: 1, title: 'they kill vampires too!', ...}
+
+ +
- or -
+ +

Use embedded documents

+
+  > db.posts.find();
+  {_id: 1, title: 'unicorns are awesome', ..., comments: [
+    {title: 'i agree', ...},
+    {title: 'they kill vampires too!', ...}
+  ]}
+
\ No newline at end of file diff --git a/_includes/fk_vs_ed/3.html b/_includes/fk_vs_ed/3.html new file mode 100644 index 0000000..331c9d1 --- /dev/null +++ b/_includes/fk_vs_ed/3.html @@ -0,0 +1,5 @@ +
+ Don't worry, this means that you get it +
+ +
Both solutions have their strengths and weaknesses. Learn to use both
diff --git a/_includes/fk_vs_ed/4.html b/_includes/fk_vs_ed/4.html new file mode 100644 index 0000000..eef891c --- /dev/null +++ b/_includes/fk_vs_ed/4.html @@ -0,0 +1,14 @@ +
Separate collections offer the greatest querying flexibility
+ +
+  // sort comments however you want
+  > db.comments.find({post_id: 3}).sort({votes: -1}).limit(5)
+  
+  // pull out one or more specific comment(s)
+  > db.comments.find({post_id: 3, user: 'leto'})
+  
+  // get a all of a user's comments joining the posts to get the title
+  > var comments = db.comments.find({user: 'leto'}, {post_id: true, votes: true})
+  > var postIds = comments.map(function(c) { return c.post_id; });
+  > db.posts.find({_id: {$in: postIds}}, {title: true});
+
\ No newline at end of file diff --git a/_includes/fk_vs_ed/5.html b/_includes/fk_vs_ed/5.html new file mode 100644 index 0000000..837d106 --- /dev/null +++ b/_includes/fk_vs_ed/5.html @@ -0,0 +1,15 @@ +
Selecting embedded documents is more limited
+ +
+  // you can select a range (useful for paging)
+  // but can't sort, so you are limited to the insertion order
+  > db.posts.find({_id: 3}, {comments: {$slice: [0, 5]}})
+  
+  // you can select the post without any comments also
+  > db.posts.find({_id: 54}, {comments: -1})
+
+  // you can't use the update's position operator ($) for field selections
+  > db.posts.find({'comments.user': 'leto'}, {title: 1, 'comments.$': 1})
+
+ +
(there are two separate features, currently in planning/development, which should address this)
\ No newline at end of file diff --git a/_includes/fk_vs_ed/6.html b/_includes/fk_vs_ed/6.html new file mode 100644 index 0000000..290c5ee --- /dev/null +++ b/_includes/fk_vs_ed/6.html @@ -0,0 +1,3 @@ +
A document, including all its embedded documents and arrays, cannot exceed 16MB
+ +
Don't freak out, The Complete Works of William Shakespeare is around 5.5MB
\ No newline at end of file diff --git a/_includes/fk_vs_ed/7.html b/_includes/fk_vs_ed/7.html new file mode 100644 index 0000000..9770b3c --- /dev/null +++ b/_includes/fk_vs_ed/7.html @@ -0,0 +1,10 @@ +
Separate collections require more work
+ +
+  // finding a post + its comments is two queries and require extra work
+  // in your code to make it all pretty (or your ODM might do it for you)
+  > db.posts.find({_id: 9001});
+  > db.comments.find({post_id: 9001})
+
+ +
this also takes [a bit] more space (+1 field, +1 index)
\ No newline at end of file diff --git a/_includes/fk_vs_ed/8.html b/_includes/fk_vs_ed/8.html new file mode 100644 index 0000000..be6f7e0 --- /dev/null +++ b/_includes/fk_vs_ed/8.html @@ -0,0 +1,6 @@ +
Embedded documents are easy and fast (single seek)
+ +
+  // finding a post + its comments
+  > db.posts.find({_id: 9001});
+
\ No newline at end of file diff --git a/_includes/fk_vs_ed/9.html b/_includes/fk_vs_ed/9.html new file mode 100644 index 0000000..08c5bf6 --- /dev/null +++ b/_includes/fk_vs_ed/9.html @@ -0,0 +1,14 @@ +
No big differences for inserts and updates
+ +
+  // separate collection insert and update
+  > db.comments.insert({post_id: 43, title: 'i hate unicrons', user: 'dracula'});
+  > db.comments.update({_id: 4949}, {$set : {tiltle: 'i hate unicorns'}});
+  
+  // embedded document insert and update
+  > db.posts.update({_id: 43}, {$push: {title: 'lol @ emo vampire', user: 'paul'}})
+  // this specific update requires that we store an _id with each comment
+  > db.posts.update( {'comments._id': 4949}, {$inc:{'comments.$.votes':1}})
+
+ +
documents that grow, like inserting new comments, will have a padding factor
\ No newline at end of file diff --git a/_layouts/bare.html b/_layouts/bare.html new file mode 100644 index 0000000..6ac734e --- /dev/null +++ b/_layouts/bare.html @@ -0,0 +1,23 @@ + + + + {{ page.title }} + + {% for font in page.fonts %} + + {% endfor %} + {% if page.css %}{% endif %} + + + {% if page.multi %}{% endif %} + + +
{{ content }}
+ + + + + diff --git a/assets/css/main.css b/assets/css/main.css new file mode 100644 index 0000000..45d5d2c --- /dev/null +++ b/assets/css/main.css @@ -0,0 +1,20 @@ +*{padding:0;margin:0;border:none;} +body{font-family:verdana;background:#222;color:#fff;} +a{text-decoration:none;color:#c35617;} + +#page a:hover{text-decoration:underline;} +#multi{display:none;} +#leaf{position:fixed;bottom:0;width:23px;height:50px;right:50px;cursor:pointer} +#footer{height:35px;width:100%;position:absolute;bottom:0;display:none;text-align:right;} +#footer a{color:#fff;padding:2px 0;margin-right:40px;text-decoration:none;border:2px solid transparent;} +#footer a:hover{border-bottom-color:#fff} + +#next, #prev{position:absolute;top:0;right:0;height:100%;width:50px;color:#222;font-size:32px;} +#prev{left:0;} +#next:hover, #prev:hover {color:#111;background:#333;text-shadow:0 0 20px #fff;} +#next:hover{border-left:1px solid #444;} +#prev:hover{border-right:1px solid #444;} +#next span, #prev span{position:absolute;top:50%;width:100%;text-align:center;} +#next span:after{content:'\276f'} +#prev span:after{content:'\276e'} +#pager{position:fixed;bottom:25px;left:25px;color:#888;font-size:80%;} \ No newline at end of file diff --git a/assets/i/leaf.png b/assets/i/leaf.png new file mode 100644 index 0000000000000000000000000000000000000000..4639243f90e05841c4660f3f14b046826979c866 GIT binary patch literal 1504 zcmV<61t0o}P)+@>+GLN zAlW5}iNT1v24gN7L`76kl&E1(CU^;GL_`n|ipO{fB8aC2Z;JtQ2n77aETRaSpn(_= z^$;;X8bgR#%}REh)LOdsVgKg~k0es0bk`k~01A>~9bJ z^5^-FqDF&;DbdBHOMM@R8!@GEO06i~+Kl6Oqo{Ezl8xVo0hi27y^YLuC0p5$sqB4t zzloS$u?+)F4&lIEc<^h*yiE%8_)F;eWQoz+If+gbG`NUzHy-*FkIpDo;68ThK8TJxa_$tls|Ge~m9_@;0&F7exys1dN`Bo1Z}(}B^+#Dh9W93V zYPl2k&OmU;tqriZ45XnVpLI8o{)hkwn)kxyx+fGs#sHQv?+4f|InTb#a?TBWfLmJ* zz$R;+GZ|xEm63X}phE*%S`?MuTVF%A3HGx88`Pr6+8#{VGrF4FIP^%*|jdf~DNjfhr zh*gwlFB^<)DWVKObXD# z-IP>ont^SP0D61Lx5zo?>I7DEjC+qdc>cv3bf*TtSvjtS3z|ALI-q1R;au~)y5bZ= z-4Vf)88(Z6D3xLc5+&DEPN*z6=K!QAvJdVzM5v~GP&1*Te3LHCi#+;Rh}s-hGZ|VZ zK?|o+1KLP4)L74b?v-7zjU&R+!r?4w%SfcfVE~M`-PDwcD_@B;Eef90(>m8~@E3y? zzFw##pqh;I=#FzsOAXNn7VNao9nJYt5j+9aFqOLj;gGqizaG>qV^c(DU1n1*3M+5n zO}5@%1d>*d418JB@>32bj9$4yP3bkWdy`%Y>AE=+p*pTiAo$dfrN*kr<{dIo8UzZJ zQ`*_@(0+xv8uotb^{J^+!u|F{-)iu4fcwhj3*{{sPBDHO<^W(|(f$K=!li`|@|3u+1@DtiU=<;5j8n=Hb-ax6U zr=I&>dOi;OjPw0@u_Dd`;52(_wa~tmDE5#Lj0Z%4wVLT|$^*NSivPtAZ?N^KP>B~@ z2E310;NmgZA?L1?sGT7h9Rbk1D*Cz!wgY6GM`$>RmQlY}+0F&F3a{doe^9<^v{KN! zr5Yx4)um_E^d`nWk=b2@HYuq3L2myWzdwrs{!&y2~V zMpCog&gDvrcy1TIUJGvi2L!|C==>=7z7Q)(Ya3&`H}`B-zLhHuf!WY9p5@IQE1hG=aVvyugf_3xfvx(a~tpN zxAN!U)Jg{bg8-I5nn~O|*J`C#<2Wf!8hyc&q&3vPHy}xsB+ZLydV|n?hRKdm+8P}e zoZ_T;ZFF=zYPQnhz+36?;Gku3Y<%jbbfj%h)cwo<0t^5Txys}QtGsXk0000$1')) + }) +}); + +$.fn.visible = function() { + return this.is(':visible'); +}; \ No newline at end of file diff --git a/assets/js/multi.js b/assets/js/multi.js new file mode 100644 index 0000000..868845f --- /dev/null +++ b/assets/js/multi.js @@ -0,0 +1,84 @@ +$(document).ready(function() { + var $body = $('body'); + var $pages = $('#multi > div'); + var $container = $('#page'); + var $pager = $('
').appendTo($body); + $('').attr({id: 'next', href: '#'}).click(nextPage).append('').appendTo($body); + $('').attr({id: 'prev', href: '#'}).click(previousPage).append('').appendTo($body); + multi = {current: null, count: $pages.length}; + + $.address.strict(false); + $.address.init(function(e) { + var page = parseInt(e.value); + if (isNaN(page)) { page = 1; } + loadPage(page); + multi.current = page; + }); + + $(document).keydown(function(e) { + var code = e.keyCode; + if (code == 39 || code == 32) { + return nextPage(); + } + if (code == 37) { + return previousPage(); + } + }); + + function nextPage() { + loadPage(multi.current + 1); + return false; + } + + function previousPage() { + loadPage(multi.current - 1); + return false; + } + + function loadPage(index) { + if (index > multi.count || index < 1) { return; } + + $body.removeClass('first last') + if (index == 1) { $body.addClass('first'); } + if (index == multi.count) { $body.addClass('last'); } + + $container.empty().append($pages.eq(index-1)); + var text = index + ' of ' + multi.count; + if (!multi.loaded) { + multi.loaded = true; + text += ' (use your arrow keys)'; + } + $pager.text(text); + $.address.value(index); + multi.current = index; + } +}); + + + +/* + * jQuery Address Plugin v${version} + * http://www.asual.com/jquery/address/ + * + * Copyright (c) 2009-2010 Rostislav Hristov + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + */ +(function(c){c.address=function(){var n=function(a){c(c.address).trigger(c.extend(c.Event(a),function(){for(var a={},d=c.address.parameterNames(),e=0,f=d.length;e"+l.title.replace("'","\\'")+"