<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

 <title>Mike Dirolf</title>
 <link href="http://dirolf.com/atom.xml" rel="self"/>
 <link href="http://dirolf.com/"/>
 <updated>2023-12-18T16:42:54+00:00</updated>
 <id>http://dirolf.com/</id>
 <author>
   <name>Mike Dirolf</name>
   <email>mike@dirolf.com</email>
 </author>

 
 <entry>
   <title>A _New Perspective_ on _MongoDB_</title>
   <link href="http://dirolf.com/2011/03/28/new-perspective-on-mongodb.html"/>
   <updated>2011-03-28T00:00:00+00:00</updated>
   <id>http://www.dirolf.com/2011/03/28/new-perspective-on-mongodb</id>
   <content type="html">&lt;p&gt;I’ve been nominally using MongoDB since 2008, but most of my experience
has been as a MongoDB developer, not a real end user. Over the past few
months I’ve made the transition to other side, &lt;em&gt;using&lt;/em&gt; MongoDB rather
than developing it. The project I’ve been working on,
&lt;a href=&quot;https://fiesta.cc&quot;&gt;fiesta&lt;/a&gt;, uses MongoDB exclusively for data storage.
Here are some thoughts on MongoDB from my new perspective.&lt;/p&gt;

&lt;h2 id=&quot;flexibility&quot;&gt;Flexibility&lt;/h2&gt;

&lt;p&gt;In the &lt;a href=&quot;/talks.html&quot;&gt;presentations&lt;/a&gt; I’ve done about MongoDB, I have
always made a point to talk about how the document-oriented data model
makes the database very flexible. I’d generally cite the example of how,
when working with the folks at Business Insider, we’d seen the need to
run any sort of migrations basically disappear. I’d explain how
documents in a collection can have any “shape”, and how doing migrations
was often as simple as adding an extra key when saving new documents.
Sometimes people didn’t quite buy this. Now that I have some concrete
examples from fiesta, maybe I can explain a little better.&lt;/p&gt;

&lt;p&gt;When I first implemented fiesta, lists would always “munge” the Reply-To
header when distributing a message. I like this behavior. Some others
&lt;a href=&quot;http://marc.merlins.org/netrants/reply-to-harmful.html&quot;&gt;don’t&lt;/a&gt;. It
pretty quickly became apparent that deciding either way would leave
roughly 50 percent of my users unhappy, so reply-to munging became one
of the (few) configurable bits of functionality in fiesta.&lt;/p&gt;

&lt;p&gt;To implement this, all I needed to do was add a boolean &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;munge&quot;&lt;/code&gt; field
to the documents in the users collection. That key is set when a user
chooses their reply-to preference. When sending a message to a user, we
have to be careful to check if that key exists, though, since some users
predate the munge setting:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;munge&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;do_munge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(...)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;That’s it! No migration.&lt;/p&gt;

&lt;h2 id=&quot;dynamic-queries&quot;&gt;Dynamic Queries&lt;/h2&gt;

&lt;p&gt;Another feature I always tout when presenting MongoDB is its dynamic
query language. The claims:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Being able to create queries on the fly makes development really
fast.&lt;/li&gt;
  &lt;li&gt;The document-based query language looks and feels totally natural in
dynamic languages.&lt;/li&gt;
  &lt;li&gt;Dynamic queries make administration easier.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After using MongoDB in the real world for a while, I feel those claims
have proven to be pretty accurate:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;When I first started development on fiesta, the queries I was
running changed probably every five minutes or so. Being able to
quickly experiment with new queries (especially from the shell) kept
the pace of development fast.&lt;/li&gt;
  &lt;li&gt;I write all of my queries directly against PyMongo, and it just
feels natural. I have noted, however, that my memory of some of the
$ operators has started to fade a bit. From time to time I’ll have
to go check the reference – makes me wish I had held onto one of
those &lt;a href=&quot;http://www.10gen.com/reference&quot;&gt;quick reference cards&lt;/a&gt; for
myself!&lt;/li&gt;
  &lt;li&gt;To be honest I can’t think of any administrative tasks that I’ve had
to do that have been much easier with dynamic queries then they
would’ve been with a few well-designed views. So this one might be a
push – I’ll keep this updated if I think of any.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;replication&quot;&gt;Replication&lt;/h2&gt;

&lt;p&gt;I stopped working full-time on MongoDB right around the time that
replica sets went out in a production release. Even since then they have
come a long way; at this point they really couldn’t be much easier to
work with.&lt;/p&gt;

&lt;p&gt;When I first deployed fiesta in beta, it was running on a single EC2
micro instance. I had set up nightly backups (using the fsync and lock
command), but didn’t have replication set up. Needless to say, I was
given a bit of a hard time when the 10gen gang heard that – hadn’t we
(myself included) always said to never run without replication? Their
ribbing was enough to convince me to take the time to set up
replication, which took all of about an hour. And most of that time was
spent playing around with &lt;a href=&quot;http://www.puppetlabs.com/&quot;&gt;puppet&lt;/a&gt; (time
well spent, for the record). Now fiesta is running on a three-node
replica set, with one passive node. The passive node is responsible for
taking nightly backups.&lt;/p&gt;

&lt;h2 id=&quot;administration&quot;&gt;Administration&lt;/h2&gt;

&lt;p&gt;Another thing I’ve often talked about is the MongoDB admin interface /
web console. This has been really useful, especially the replica set UI.
The one issue I’ve run into with it is documented
&lt;a href=&quot;http://jira.mongodb.org/browse/SERVER-1729&quot;&gt;here&lt;/a&gt;, but it’s far from a
show stopper.&lt;/p&gt;

&lt;p&gt;For administration I’ve found Elliot’s &lt;a href=&quot;https://github.com/erh/mongo-munin&quot;&gt;munin
plugins&lt;/a&gt; to be even more useful than
I expected. If you’re running MongoDB in production you should
definitely check them out.&lt;/p&gt;

&lt;h2 id=&quot;performance&quot;&gt;Performance&lt;/h2&gt;

&lt;p&gt;So far, so good. More updates here once fiesta hits its millionth user.
Oh, by the way, you should &lt;a href=&quot;https://fiesta.cc&quot;&gt;give it a shot&lt;/a&gt; if you
haven’t already :).&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Create a _Mailing List_ With _fiesta.cc_</title>
   <link href="http://dirolf.com/2011/03/09/create-a-mailing-list-with-fiesta.cc.html"/>
   <updated>2011-03-09T00:00:00+00:00</updated>
   <id>http://www.dirolf.com/2011/03/09/create-a-mailing-list-with-fiesta.cc</id>
   <content type="html">&lt;p&gt;&lt;img src=&quot;/images/fiesta.png&quot; width=&quot;350&quot; height=&quot;76&quot; style=&quot;float: left; padding: 0.5em 2em 0.5em 0em;&quot; /&gt;&amp;lt;/a&amp;gt;&lt;/p&gt;

&lt;p&gt;Over the past few months I’ve been working on a project called
&lt;a href=&quot;https://fiesta.cc&quot;&gt;fiesta.cc&lt;/a&gt;. I thought I’d do a quick post
to explain what fiesta.cc is, and share an invite code so you can try it
out!&lt;/p&gt;

&lt;p&gt;The goal with fiesta.cc is to make it easy to communicate with groups
using email. The current state of the art here seems to be a choice of:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Reply-all chains (Someone sends an email to a bunch of addresses. To
send a message to the group others reply-all). These are great
because creating a group is trivial. These are bad because:
    &lt;ul&gt;
      &lt;li&gt;Group members can never unsubscribe, be removed, or change their
email address, and new members can’t be added: someone ends up
replying to an old message with the old set of addresses. This
is really bad for groups like sports teams, which might be
relatively consistent but have a few roster changes each season.&lt;/li&gt;
      &lt;li&gt;Replying to a thread is easy, but sending a new message to the
list is hard. You need to find an old message and reply to that,
or retype the addresses. Either of those options is frustrating
in general and pretty much unusable from a mobile device.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Client-side group expansion. Some mail clients allow users to create
a list of addresses that can be aliased to a single group name. For
everybody but the original sender, these have all the problems of a
reply-all chain; the group isn’t shared to other list members.&lt;/li&gt;
  &lt;li&gt;Services like google/yahoo groups or posterous, or old school
listservs (set up manually or through an IT department). These
options solve all of the problems with (1) and (2) but they are
&lt;em&gt;much&lt;/em&gt; more work than something like (1).&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;an-easier-way&quot;&gt;An Easier Way&lt;/h2&gt;

&lt;p&gt;Here’s how to create a mailing list for your soccer team using
fiesta.cc:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Send an email to the members of your list (just like you would in a
reply-all chain).&lt;/li&gt;
  &lt;li&gt;CC soccer@fiesta.cc (or any other list name @fiesta.cc).&lt;/li&gt;
  &lt;li&gt;You’re done!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is great because it’s as easy to set up as a reply-all chain (just
add one more address), but it gives you all of the benefits of a real
mailing list! When any list member emails soccer@fiesta.cc it’ll go to
the whole list. People can unsubscribe or be added/removed at any time.
They can also change their email address.&lt;/p&gt;

&lt;p&gt;The really cool part is that you don’t need to reserve a group name or
worry about conflicts with other groups: fiesta.cc ties group names to
the sender of a message. That means that you can have a list called
family@fiesta.cc which is totally separate from my family@fiesta.cc
list. The site has more details about
&lt;a href=&quot;https://fiesta.cc/learn&quot;&gt;how to create and manage mailing
lists&lt;/a&gt; with fiesta.cc.&lt;/p&gt;

&lt;h2 id=&quot;beta-invite&quot;&gt;Beta Invite&lt;/h2&gt;

&lt;p&gt;I think that fiesta.cc is a really useful service already, and the
feedback from users so far has been very positive. I’d love for readers
of this blog to check it out and send any feedback my way.&lt;/p&gt;

&lt;h3 id=&quot;click-here-for-an-invite&quot;&gt;&lt;a href=&quot;https://fiesta.cc/?i=1&amp;amp;c=dirolf&quot;&gt;Click here for an invite&lt;/a&gt;.&lt;/h3&gt;

&lt;p&gt;The invite will let you see the homepage, just follow the steps there to
create your first list and get an account. It’s simple enough that it
makes sense to use even for small groups (like family@fiesta.cc or
roommates@fiesta.cc) and temporary groups (like
birthdayparty@fiesta.cc).&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>_MongoDB_ Contest _Winners_</title>
   <link href="http://dirolf.com/2011/01/07/mongodb-contest-winners.html"/>
   <updated>2011-01-07T00:00:00+00:00</updated>
   <id>http://www.dirolf.com/2011/01/07/mongodb-contest-winners</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;http://www.amazon.com/gp/product/1449381561?ie=UTF8&amp;amp;tag=mikdir-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=390957&amp;amp;creativeASIN=1449381561&quot;&gt;&lt;img src=&quot;/images/mongodb_tdg.jpg&quot; width=&quot;250&quot; height=&quot;328&quot; style=&quot;float: right; padding: 0.5em 0 0.5em 2em;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It has been about a week since I announced that I was &lt;a href=&quot;/2010/12/30/mongodb-the-definitive-guide-giveaway.html&quot;&gt;giving
away&lt;/a&gt; of copies
of
&lt;a href=&quot;http://www.amazon.com/gp/product/1449381561?ie=UTF8&amp;amp;tag=mikdir-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=390957&amp;amp;creativeASIN=1449381561&quot;&gt;MongoDB:
The Definitive
Guide&lt;/a&gt;&lt;img src=&quot;http://www.assoc-amazon.com/e/ir?t=mikdir-20&amp;amp;l=as2&amp;amp;o=1&amp;amp;a=1449381561&quot; width=&quot;1&quot; height=&quot;1&quot; border=&quot;0&quot; alt=&quot;&quot; style=&quot;border:none !important; margin:0px !important;&quot; /&gt;.
So, it’s time to announce the winners!&lt;/p&gt;

&lt;p&gt;I did a random drawing of the people who commented on the post (only
including those who actually listed their favorite restaurant!). The
winners are (drum roll):&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Rob D (Robdoherty2)&lt;/li&gt;
  &lt;li&gt;Shehab Hamad&lt;/li&gt;
  &lt;li&gt;Sam Sen&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you’re one of the winners, please send me an email (address is in the
header of this site) with your address and we’ll figure out how to get
you your copy! If you didn’t win, don’t lose all hope: if any of the
winners don’t pipe up within the next week, I’ll pick a new name. If all
the prizes are claimed, or they aren’t but you still don’t win, send me
an email and I’ll set you up with a nice discount on the book (contest
participants only, please).&lt;/p&gt;

&lt;p&gt;Thanks for playing!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>_MongoDB_: The Definitive Guide _Giveaway_</title>
   <link href="http://dirolf.com/2010/12/30/mongodb-the-definitive-guide-giveaway.html"/>
   <updated>2010-12-30T00:00:00+00:00</updated>
   <id>http://www.dirolf.com/2010/12/30/mongodb-the-definitive-guide-giveaway</id>
   <content type="html">&lt;p&gt;Updated 2011-1-7: The contest is closed and the winners have been
&lt;a href=&quot;/2011/01/07/mongodb-contest-winners.html&quot;&gt;announced&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.amazon.com/gp/product/1449381561?ie=UTF8&amp;amp;tag=mikdir-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=390957&amp;amp;creativeASIN=1449381561&quot;&gt;&lt;img src=&quot;/images/mongodb_tdg.jpg&quot; width=&quot;250&quot; height=&quot;328&quot; style=&quot;float: left; padding: 0.5em 2em 0.5em 0;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I don’t think I’ve mentioned it here, but a few months ago
&lt;a href=&quot;http://www.snailinaturtleneck.com/&quot;&gt;Kristina&lt;/a&gt; and I finished writing
&lt;a href=&quot;http://www.amazon.com/gp/product/1449381561?ie=UTF8&amp;amp;tag=mikdir-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=390957&amp;amp;creativeASIN=1449381561&quot;&gt;MongoDB:
The Definitive
Guide&lt;/a&gt;&lt;img src=&quot;http://www.assoc-amazon.com/e/ir?t=mikdir-20&amp;amp;l=as2&amp;amp;o=1&amp;amp;a=1449381561&quot; width=&quot;1&quot; height=&quot;1&quot; border=&quot;0&quot; alt=&quot;&quot; style=&quot;border:none !important; margin:0px !important;&quot; /&gt;.
Writing the book was a big undertaking, and for a while it seemed like
it would take a miracle just to finish it on time. Well, to make a long
story short, the book is finished and it’s on the shelves.&lt;/p&gt;

&lt;p&gt;I have a couple of extra copies of TDG that have been collecting dust in
my apartment, and, after tripping over them for the past two months,
I’ve decided to give them away! There are three copies up for grabs,
each of which will be signed by me (and hopefully by Kristina too, if I
see her soon enough). To enter the contest, leave a note in the comments
with your name &lt;em&gt;and&lt;/em&gt; the name of your favorite restaurant. In a week or
so I’ll (randomly) select the winners and announce them in another post.
I’ll pay for shipping in the US, but if you’re in a different country
I’ll probably ask you to foot that bill. Good luck!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Connecting to a _Replica Set_ from _PyMongo_</title>
   <link href="http://dirolf.com/2010/08/16/pymongo-replica-sets.html"/>
   <updated>2010-08-16T00:00:00+00:00</updated>
   <id>http://www.dirolf.com/2010/08/16/pymongo-replica-sets</id>
   <content type="html">&lt;p&gt;PyMongo makes working with “replica sets”:http://dochub.mongodb.org/core/rs easy. Here we’ll launch a new replica set and show how to handle both initialization and normal connections with PyMongo. This blog post will also be going up as an example in the “PyMongo docs”:http://api.mongodb.org/python/current/examples/index.html - check that page out for more examples of how to get things done with PyMongo.&lt;/p&gt;

&lt;p&gt;Replica sets require server version &lt;strong&gt;&lt;span style=&quot;text-align:right;&quot;&gt;=
1.6.0&lt;/span&gt;&lt;/strong&gt;. Support for connecting to replica sets also requires
PyMongo version &lt;strong&gt;&lt;span style=&quot;text-align:right;&quot;&gt;= 1.8.0&lt;/span&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;h2 id=&quot;starting-a-replica-set&quot;&gt;Starting a Replica Set&lt;/h2&gt;

&lt;p&gt;The main &lt;a href=&quot;http://dochub.mongodb.org/core/rs&quot;&gt;replica set documentation&lt;/a&gt;
contains extensive information about setting up a new replica set or
migrating an existing MongoDB setup, be sure to check that out. Here,
we’ll just do the bare minimum to get a three node replica set setup
locally.&lt;/p&gt;

&lt;p&gt;Replica sets should always use multiple nodes in production - putting
all set members on the same physical node is only recommended for
testing and development.&lt;/p&gt;

&lt;p&gt;We start three &lt;code&gt;mongod&lt;/code&gt; processes, each on a different port
and with a different dbpath, but all using the same replica set name
“foo”. In the example we use the hostname “morton.local”, so replace
that with your hostname when running:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;hostname
&lt;/span&gt;morton.local
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mongod &lt;span class=&quot;nt&quot;&gt;--replSet&lt;/span&gt; foo/morton.local:27018,morton.local:27019 &lt;span class=&quot;nt&quot;&gt;--rest&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mongod &lt;span class=&quot;nt&quot;&gt;--port&lt;/span&gt; 27018 &lt;span class=&quot;nt&quot;&gt;--dbpath&lt;/span&gt; /data/db1 &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--replSet&lt;/span&gt; foo/morton.local:27017 &lt;span class=&quot;nt&quot;&gt;--rest&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mongod &lt;span class=&quot;nt&quot;&gt;--port&lt;/span&gt; 27019 &lt;span class=&quot;nt&quot;&gt;--dbpath&lt;/span&gt; /data/db2 &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--replSet&lt;/span&gt; foo/morton.local:27017 &lt;span class=&quot;nt&quot;&gt;--rest&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;initializing-the-set&quot;&gt;Initializing the Set&lt;/h2&gt;

&lt;p&gt;At this point all of our nodes are up and running, but the set has yet
to be initialized. Until the set is initialized no node will become the
primary, and things are essentially “offline”.&lt;/p&gt;

&lt;p&gt;To initialize the set we need to connect to a single node and run the
initiate command. Since we don’t have a primary yet, we’ll need to tell
PyMongo that it’s okay to connect to a slave/secondary:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-pycon&quot; data-lang=&quot;pycon&quot;&gt;&amp;gt;&amp;gt;&amp;gt; from pymongo import Connection
&amp;gt;&amp;gt;&amp;gt; c = Connection(&quot;morton.local:27017&quot;, slave_okay=True)&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We could have connected to any of the other nodes instead, but only the
node we initiate from is allowed to contain any initial data.&lt;/p&gt;

&lt;p&gt;After connecting, we run the initiate command to get things started
(here we just use an implicit configuration, for more advanced
configuration options see the replica set documentation):&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-pycon&quot; data-lang=&quot;pycon&quot;&gt;&amp;gt;&amp;gt;&amp;gt; c.admin.command(&quot;replSetInitiate&quot;)
{u'info': u'Config now saved locally.  ...',
 u'info2': u'no configuration explicitly specified -- making one',
 u'ok': 1.0}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The three &lt;code&gt;mongod&lt;/code&gt; servers we started earlier will now
coordinate and come online as a replica set.&lt;/p&gt;

&lt;h2 id=&quot;connecting-to-a-replica-set&quot;&gt;Connecting to a Replica Set&lt;/h2&gt;

&lt;p&gt;The initial connection as made above is a special case, for an
uninitialized replica set. Normally we’ll want to connect differently. A
connection to a replica set can be made using the normal
&lt;code&gt;Connection()&lt;/code&gt; constructor, specifying one or more members of
the set. For example, any of the following will create a connection to
the set we just created:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-pycon&quot; data-lang=&quot;pycon&quot;&gt;&amp;gt;&amp;gt;&amp;gt; Connection(&quot;morton.local&quot;)
&amp;gt;&amp;gt;&amp;gt; Connection(&quot;morton.local:27018&quot;)
&amp;gt;&amp;gt;&amp;gt; Connection(&quot;morton.local&quot;, 27019)
&amp;gt;&amp;gt;&amp;gt; Connection([&quot;morton.local:27018&quot;, &quot;morton.local:27019&quot;])
&amp;gt;&amp;gt;&amp;gt; Connection(&quot;morton.local:27017,morton.local:27018,morton.local:27019&quot;)&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The nodes passed to &lt;code&gt;Connection()&lt;/code&gt; are called the &lt;strong&gt;seeds&lt;/strong&gt;.
As long as at least one of the seeds is online, the driver will be able
to “discover” all of the nodes in the set and make a connection to the
current primary.&lt;/p&gt;

&lt;h2 id=&quot;handling-failover&quot;&gt;Handling Failover&lt;/h2&gt;

&lt;p&gt;When a failover occurs, PyMongo will automatically attempt to find the
new primary node and perform subsequent operations on that node. This
can’t happen completely transparently, however. Here we’ll perform an
example failover to illustrate how everything behaves. First, we’ll
connect to the replica set and perform a couple of basic operations:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-pycon&quot; data-lang=&quot;pycon&quot;&gt;&amp;gt;&amp;gt;&amp;gt; db = Connection(&quot;morton.local&quot;).test
&amp;gt;&amp;gt;&amp;gt; db.test.save({&quot;x&quot;: 1})
ObjectId('...')
&amp;gt;&amp;gt;&amp;gt; db.test.find_one()
{u'x': 1, u'_id': ObjectId('...')}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;By checking the host and port, we can see that we’re connected to
&lt;strong&gt;morton.local:27017&lt;/strong&gt;, which is the current primary:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-pycon&quot; data-lang=&quot;pycon&quot;&gt;&amp;gt;&amp;gt;&amp;gt; db.connection.host
'morton.local'
&amp;gt;&amp;gt;&amp;gt; db.connection.port
27017&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now let’s bring down that node and see what happens when we run our
query again:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-pycon&quot; data-lang=&quot;pycon&quot;&gt;&amp;gt;&amp;gt;&amp;gt; db.test.find_one()
Traceback (most recent call last):
pymongo.errors.AutoReconnect: ...&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We get an &lt;code&gt;AutoReconnect&lt;/code&gt; exception. This means that the
driver was not able to connect to the old primary (which makes sense, as
we killed the server), but that it will attempt to automatically
reconnect on subsequent operations. When this exception is raised our
application code needs to decide whether to retry the operation or to
simply continue, accepting the fact that the operation might have
failed.&lt;/p&gt;

&lt;p&gt;On subsequent attempts to run the query we might continue to see this
exception. Eventually, however, the replica set will failover and elect
a new primary (this should take a couple of seconds in general). At that
point the driver will connect to the new primary and the operation will
succeed:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-pycon&quot; data-lang=&quot;pycon&quot;&gt;&amp;gt;&amp;gt;&amp;gt; db.test.find_one()
{u'x': 1, u'_id': ObjectId('...')}
&amp;gt;&amp;gt;&amp;gt; db.connection.host
u'morton.local'
&amp;gt;&amp;gt;&amp;gt; db.connection.port
27018&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;If you have any questions on working with Replica Sets and PyMongo, feel
free to ask in the comments!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>_Hackabit_ and _be bit.ly_</title>
   <link href="http://dirolf.com/2010/07/15/hackabit.html"/>
   <updated>2010-07-15T00:00:00+00:00</updated>
   <id>http://www.dirolf.com/2010/07/15/hackabit</id>
   <content type="html">&lt;p&gt;Last night the folks at &lt;a href=&quot;http://bit.ly&quot;&gt;bit.ly&lt;/a&gt; hosted a hackathon,
called &lt;a href=&quot;http://hackabit.com&quot;&gt;hackabit&lt;/a&gt;, to celebrate their 2nd
anniversary (congratulations guys!). It was awesome; there were a bunch
of us there from &lt;a href=&quot;http://www.10gen.com&quot;&gt;10gen&lt;/a&gt;, the bit.ly people are
great, and it was fun just hanging out and working on stuff. There was a
lot of coding being done, but I don’t have links to much of it (one cool
project was a Python &lt;a href=&quot;http://pypi.python.org/pypi/urlnorm&quot;&gt;url normalization
library&lt;/a&gt; by Jehiah). If anybody has
links to other projects people were working on, let me know.&lt;/p&gt;

&lt;p&gt;I wanted to do &lt;a href=&quot;/2007/11/zoomix-another-javascript-game.html&quot;&gt;yet&lt;/a&gt;
&lt;a href=&quot;/2007/06/fun-game.html&quot;&gt;another&lt;/a&gt; quick JS game, and also wanted to do
something bit.ly themed. The result is &lt;a href=&quot;/bebitly**&quot;&gt;be bit.ly&lt;/a&gt; - a game
where you play the role of the bit.ly website, by shortening incoming
urls and turning shortened urls back into long ones. It sounds a bit
strange, but I think it came out okay - hope you enjoy it! I know there
are some rough edges, but time was short. Let me know what you think in
the comments.&lt;/p&gt;

&lt;p&gt;Edit: Chris also created a bit.ly inspired game at hackabit, &lt;a href=&quot;http://cjt.us/bitly/&quot;&gt;Bitly
Sea&lt;/a&gt; - it’s pretty fun, check it out!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>_PyMongo_ _1.7_ Released</title>
   <link href="http://dirolf.com/2010/06/17/pymongo-1.7-released.html"/>
   <updated>2010-06-17T00:00:00+00:00</updated>
   <id>http://www.dirolf.com/2010/06/17/pymongo-1.7-released</id>
   <content type="html">&lt;p&gt;A new release for “PyMongo”:http://api.mongodb.org/python has been long overdue – the last release (1.6) was made on May 11th, over two months ago! It’s been a busy couple of months with travel and “writing”:http://oreilly.com/catalog/9781449389536/ (and life), so a release hasn’t been on the top of the list. I finally made the effort to get a release out today, though, and the result is PyMongo 1.7. For a full list of changes, check the “changelog”:http://api.mongodb.org/python/1.7/changelog.html; in this post I’ll talk about a few of them in detail.&lt;/p&gt;

&lt;h2 id=&quot;using-a-dict-to-specify-fields-to-return&quot;&gt;Using a &lt;code&gt;dict&lt;/code&gt; to Specify Fields to Return&lt;/h2&gt;

&lt;p&gt;One of the smallest changes in 1.7 is that the &lt;em&gt;fields&lt;/em&gt; argument to
&lt;code&gt;find&lt;/code&gt;/&lt;code&gt;find\_one&lt;/code&gt; can now take a
&lt;code&gt;dict&lt;/code&gt; in addition to a &lt;code&gt;list&lt;/code&gt;. So, the following
two &lt;code&gt;find\_one&lt;/code&gt;s are equivalent:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-pycon&quot; data-lang=&quot;pycon&quot;&gt;&amp;gt;&amp;gt;&amp;gt; db.test.save({&quot;x&quot;: 1, &quot;y&quot;: 2, &quot;z&quot;: [1, 2, 3, 4]})
ObjectId('...')
&amp;gt;&amp;gt;&amp;gt; db.test.find_one(fields=[&quot;y&quot;])
{u'y': 2, u'_id': ObjectId('...')}
&amp;gt;&amp;gt;&amp;gt; db.test.find_one(fields={&quot;y&quot;: 1})
{u'y': 2, u'_id': ObjectId('...')}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The second call should look familiar to those who have used the MongoDB
shell extensively, while the first is a little less verbose (and has
always been the PyMongo way of doing things). Since PyMongo was first
implemented, however, there have been some new features added to the
server that are best exposed through the &lt;code&gt;dict&lt;/code&gt; interface,
like specifying keys that we &lt;em&gt;don’t&lt;/em&gt; want returned:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-pycon&quot; data-lang=&quot;pycon&quot;&gt;&amp;gt;&amp;gt;&amp;gt; db.test.find_one(fields={&quot;y&quot;: 0})
{u'x': 1, u'_id': ObjectId('...'), u'z': [1, 2, 3, 4]}
&amp;gt;&amp;gt;&amp;gt; db.test.find_one(fields={&quot;z&quot;: 0})
{u'y': 2, u'x': 1, u'_id': ObjectId('...')}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Or using the new &lt;code&gt;$slice&lt;/code&gt; operator to only return portions of
an array:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-pycon&quot; data-lang=&quot;pycon&quot;&gt;&amp;gt;&amp;gt;&amp;gt; db.test.find_one(fields={&quot;z&quot;: {&quot;$slice&quot;: 2}})
{u'y': 2, u'x': 1, u'_id': ObjectId('...'), u'z': [1, 2]}
&amp;gt;&amp;gt;&amp;gt; db.test.find_one(fields={&quot;z&quot;: {&quot;$slice&quot;: -2}})
{u'y': 2, u'x': 1, u'_id': ObjectId('...'), u'z': [3, 4]}
&amp;gt;&amp;gt;&amp;gt; db.test.find_one(fields={&quot;z&quot;: {&quot;$slice&quot;: [1, 2]}})
{u'y': 2, u'x': 1, u'_id': ObjectId('...'), u'z': [2, 3]}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;datetime-handling&quot;&gt;&lt;code&gt;datetime&lt;/code&gt; Handling&lt;/h2&gt;

&lt;p&gt;PyMongo 1.7 also improves support for working with &lt;code&gt;datetime&lt;/code&gt;
instances. The first change is that timezone aware datetimes are now
properly encoded, by converting them to UTC before saving them. Naive
datetimes will still be assumed to be in UTC.&lt;/p&gt;

&lt;p&gt;Since &lt;a href=&quot;http://bsonspec.org&quot;&gt;BSON&lt;/a&gt; is not currently capable of storing
datetimes with timezone information, all datetimes will still &lt;em&gt;decode&lt;/em&gt;
as UTC. Currently the &lt;code&gt;datetime&lt;/code&gt; instances returned will be
naive, but that will probably change in the future as well.&lt;/p&gt;

&lt;p&gt;A final change in 1.7 is that the PyMongo C extension now uses the
&lt;a href=&quot;http://code.google.com/p/y2038/&quot;&gt;y2038&lt;/a&gt; project’s implementation of
&lt;em&gt;time.h&lt;/em&gt;. This allows the C extension to properly support dates beyond
January 19, 2038. There might still be issues for users on 32-bit
platforms using the pure-Python encoder, at least for older versions of
Python.&lt;/p&gt;

&lt;h2 id=&quot;max_scan&quot;&gt;max_scan&lt;/h2&gt;

&lt;p&gt;Version 1.7 adds support for the server’s new &lt;code&gt;max\_scan&lt;/code&gt;
functionality. max_scan allows a developer to set the maximum number of
documents to scan for each individual query. This functionality can be
useful when a developer wants guaranteed performance, even if it means a
partial result set.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;max\_scan&lt;/code&gt; requires a MongoDB server version &lt;strong&gt;&lt;span style=&quot;text-align:right;&quot;&gt;= 1.5.1&lt;/span&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;max_scan can be passed as an argument to
&lt;code&gt;find&lt;/code&gt;/&lt;code&gt;find\_one&lt;/code&gt;, or can be added to a
&lt;code&gt;Cursor&lt;/code&gt; using chaining; the following two queries are
equivalent:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;a&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;max_scan&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;a&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;max_scan&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;custom-classes-for-returned-documents&quot;&gt;Custom Classes for Returned Documents&lt;/h2&gt;

&lt;p&gt;The BSON decoder in PyMongo normally decodes all documents as
&lt;code&gt;dict&lt;/code&gt;s. Version 1.7 adds the ability to specify a custom
class to decode to. All the class needs is to have a
&lt;code&gt;*setitem*&lt;/code&gt; method, which will be called for each key/value
pair in the BSON being decoded.&lt;/p&gt;

&lt;p&gt;This ability is exposed through the &lt;em&gt;as_class&lt;/em&gt; argument to
&lt;code&gt;find&lt;/code&gt;/&lt;code&gt;find\_one&lt;/code&gt;, and a new default class can be
set using a &lt;code&gt;Connection&lt;/code&gt;’s &lt;em&gt;document_class&lt;/em&gt; attribute. The
two queries below both decode to &lt;code&gt;SON&lt;/code&gt;, so that the resultant
documents maintain key order:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pymongo.son&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SON&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;find_one&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;as_class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SON&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;connection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;document_class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SON&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;find_one&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;There are a couple of cool things that fall out of this functionality.
First, third party libraries like
&lt;a href=&quot;http://bitbucket.org/namlook/mongokit/wiki/Home&quot;&gt;MongoKit&lt;/a&gt; should have
an easier time re-hydrating their models, and will probably be a little
more efficient. Second, the class used doesn’t even need to represent a
document: it can just treat &lt;code&gt;*setitem*&lt;/code&gt; like a hook, allowing
custom code to run on each key/value pair. Here, we create a custom
class that just prints key/value pairs to stdout:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-pycon&quot; data-lang=&quot;pycon&quot;&gt;&amp;gt;&amp;gt;&amp;gt; class DocPrinter(object):
...     def __setitem__(self, key, value):
...         print &quot;(%r, %r)&quot; % (key, value)
... 
&amp;gt;&amp;gt;&amp;gt; db.test.save({&quot;x&quot;: 1})
ObjectId('4c1a4ee9e6fb1b5adb000001')
&amp;gt;&amp;gt;&amp;gt; db.test.find_one(as_class=DocPrinter)
(u'_id', ObjectId('4c1a4ee9e6fb1b5adb000001'))
(u'x', 1)
&amp;lt;__main__.DocPrinter object at 0x1012d7bd0&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This example is a bit pointless, but I’m sure readers can think of much
cooler things to do with it!&lt;/p&gt;

&lt;p&gt;There’s a whole bunch more that’s new in PyMongo 1.7: check the
&lt;a href=&quot;http://api.mongodb.org/python/1.7/changelog.html&quot;&gt;changelog&lt;/a&gt; for the
full list, and go upgrade!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Videos from _MongoNYC_</title>
   <link href="http://dirolf.com/2010/06/02/videos-from-mongonyc.html"/>
   <updated>2010-06-02T00:00:00+00:00</updated>
   <id>http://www.dirolf.com/2010/06/02/videos-from-mongonyc</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;http://www.10gen.com/event_mongony_10may21&quot;&gt;MongoNYC&lt;/a&gt; happened in the
end of May and was one of my favorite conferences of the past year. All
of the talks I went to were very good, and I also had a chance to meet
and talk with a ton of interesting people. The videos from the
conference were just posted, and they can all be found
&lt;a href=&quot;http://mongodb.blip.tv/&quot;&gt;here&lt;/a&gt;. The two talks I did are embedded below,
but I’d also recommend checking out at least the talks by
&lt;a href=&quot;http://blip.tv/file/3701052&quot;&gt;Kushal&lt;/a&gt; and
&lt;a href=&quot;http://blip.tv/file/3704043&quot;&gt;Jay&lt;/a&gt;.&lt;/p&gt;

&lt;div align=&quot;center&quot;&gt;
[**Mastering the MongoDB Shell**](http://blip.tv/file/3700829)

&lt;embed src=&quot;http://blip.tv/play/AYHjhmIC&quot; type=&quot;application/x-shockwave-flash&quot; width=&quot;480&quot; height=&quot;306&quot; allowscriptaccess=&quot;always&quot; allowfullscreen=&quot;true&quot; /&gt;
&amp;lt;/embed&amp;gt;
&lt;/div&gt;
&lt;div align=&quot;center&quot;&gt;
[**Inside PyMongo**](http://blip.tv/file/3701097)

&lt;embed src=&quot;http://blip.tv/play/AYHjiG4C&quot; type=&quot;application/x-shockwave-flash&quot; width=&quot;480&quot; height=&quot;306&quot; allowscriptaccess=&quot;always&quot; allowfullscreen=&quot;true&quot; /&gt;
&amp;lt;/embed&amp;gt;
&lt;/div&gt;
&lt;p&gt;If you have any questions about my talks or the conference in general,
leave a note in the comments!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Inside _MongoDB_</title>
   <link href="http://dirolf.com/2010/05/27/inside-mongodb.html"/>
   <updated>2010-05-27T00:00:00+00:00</updated>
   <id>http://www.dirolf.com/2010/05/27/inside-mongodb</id>
   <content type="html">&lt;p&gt;Updated 2010-10-29: There is now video of this talk (from when it was
given at Mongo Boston) available
&lt;a href=&quot;http://www.10gen.com/video/mongoboston2010/mongodbinternals&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This year at &lt;a href=&quot;http://www.gluecon.com/2010/&quot;&gt;Gluecon&lt;/a&gt; I was asked to
speak about MongoDB, and specifically to give a “very technical” talk
about it. I realized that this would be a good opportunity to do a talk
other than the usual &lt;a href=&quot;/2010/04/09/introduction-to-mongodb.html&quot;&gt;introduction to
MongoDB&lt;/a&gt; and decided speak
about MongoDB internals. Here’s the deck I used:&lt;/p&gt;

&lt;div align=&quot;center&quot;&gt;
&lt;object width=&quot;425&quot; height=&quot;355&quot;&gt;
&lt;param name=&quot;movie&quot; value=&quot;http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=internals-100527122106-phpapp02&amp;amp;stripped_title=inside-mongodb-the-internals-of-an-opensource-database&quot; /&gt;&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot; /&gt;&lt;param name=&quot;allowScriptAccess&quot; value=&quot;always&quot; /&gt;&lt;embed src=&quot;http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=internals-100527122106-phpapp02&amp;amp;stripped_title=inside-mongodb-the-internals-of-an-opensource-database&quot; type=&quot;application/x-shockwave-flash&quot; allowscriptaccess=&quot;always&quot; allowfullscreen=&quot;true&quot; width=&quot;425&quot; height=&quot;355&quot; /&gt;&amp;lt;/embed&amp;gt;&lt;/object&gt;

&lt;/div&gt;
&lt;p&gt;If you have any questions or interest in hearing more about this
(perhaps a series of blog posts on MongoDB internals?), let me know in
the comments!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>_Introduction_ to _MongoDB_</title>
   <link href="http://dirolf.com/2010/04/09/introduction-to-mongodb.html"/>
   <updated>2010-04-09T00:00:00+00:00</updated>
   <id>http://www.dirolf.com/2010/04/09/introduction-to-mongodb</id>
   <content type="html">&lt;p&gt;I just finished giving a presentation introducing MongoDB at
&lt;a href=&quot;http://phillyemergingtech.com/&quot;&gt;PhillyETE&lt;/a&gt;. Here’s the deck I used; I
think video will be available soon and I’ll post that when it’s up:&lt;/p&gt;

&lt;div align=&quot;center&quot;&gt;
&lt;object width=&quot;425&quot; height=&quot;355&quot;&gt;
&lt;param name=&quot;movie&quot; value=&quot;http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=phillyete-100409154513-phpapp02&amp;amp;stripped_title=introduction-to-mongodb&quot; /&gt;&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot; /&gt;&lt;param name=&quot;allowScriptAccess&quot; value=&quot;always&quot; /&gt;&lt;embed src=&quot;http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=phillyete-100409154513-phpapp02&amp;amp;stripped_title=introduction-to-mongodb&quot; type=&quot;application/x-shockwave-flash&quot; allowscriptaccess=&quot;always&quot; allowfullscreen=&quot;true&quot; width=&quot;425&quot; height=&quot;355&quot; /&gt;&amp;lt;/embed&amp;gt;&lt;/object&gt;

&lt;/div&gt;
&lt;p&gt;I think the presentation went well, and overall the conference was
great. My favorite talk (besides the MongoDB one, of course) was one by
&lt;a href=&quot;http://twitter.com/geirmagnusson&quot;&gt;Geir&lt;/a&gt;. His talk was ostensibly about
Project Voldemort, but ended up being more about infrastructure at
&lt;a href=&quot;http://www.gilt.com/&quot;&gt;Gilt&lt;/a&gt; and the myriad approaches they’ve taken to
tackling their unique traffic patterns - very entertaining stuff.&lt;/p&gt;

&lt;p&gt;If you have any questions lingering from the presentation at PhillyETE,
or about MongoDB in general, pipe up in the comments!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Working With _Stored_ _JavaScript_ in _MongoDB_</title>
   <link href="http://dirolf.com/2010/04/05/stored-javascript-in-mongodb-and-pymongo.html"/>
   <updated>2010-04-05T00:00:00+00:00</updated>
   <id>http://www.dirolf.com/2010/04/05/stored-javascript-in-mongodb-and-pymongo</id>
   <content type="html">&lt;p&gt;Stored JS in MongoDB is saved in the special &lt;em&gt;system.js&lt;/em&gt; collection. The
documents there should be structured like:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
 &lt;span class=&quot;nx&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;strong&gt;_id&lt;/strong&gt; is the name of the function, and &lt;strong&gt;value&lt;/strong&gt; is the JS code
defining the function. Here’s an example of saving such a function and
then using it in an eval. This can be run using the MongoDB shell:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;system&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;js&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;                  &lt;span class=&quot;na&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}});&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;eval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;return sum(2, 3);&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Once &lt;code&gt;sum&lt;/code&gt; is defined we can use it from all of MongoDB’s JS
contexts, including Map/Reduce and $where. In this example we use
&lt;code&gt;sum&lt;/code&gt; within a $where clause to get all documents where the
sum of &lt;strong&gt;x&lt;/strong&gt; and &lt;strong&gt;y&lt;/strong&gt; is 6:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;$where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;sum(this.x, this.y) == 6&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;_id&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ObjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;4bba376231d25858659843f7&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;_id&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ObjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;4bba376e31d25858659843f9&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Since &lt;em&gt;system.js&lt;/em&gt; is a collection, we can perform normal MongoDB
operations on it in order to administer our stored JS functions. We
might want to list the stored functions:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;system&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;js&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;distinct&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;_id&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;or remove a function we previously stored:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;system&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;js&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;eval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;return sum(2, 3);&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;Mon&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Apr&lt;/span&gt;  &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;14&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;45&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;JS&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;uncaught&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;exception&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;errno&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;errmsg&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;[...] sum is not defined [...]&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;ok&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;stored-js-and-pymongo&quot;&gt;Stored JS and PyMongo&lt;/h2&gt;

&lt;p&gt;In version 1.5 &lt;a href=&quot;http://api.mongodb.org/python&quot;&gt;PyMongo&lt;/a&gt; added some
helpers to make working with stored JS incredibly easy. The API is
accessed through the &lt;code&gt;Database.system\_js&lt;/code&gt; property, which
returns an instance of the &lt;a href=&quot;http://api.mongodb.org/python/1.5.2%2B/api/pymongo/database.html#pymongo.database.SystemJS&quot;&gt;SystemJS helper
class&lt;/a&gt;.
The SystemJS class allows us to add, call, and remove stored JS
functions using a nice Pythonic interface:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-pycon&quot; data-lang=&quot;pycon&quot;&gt;&amp;gt;&amp;gt;&amp;gt; db.system_js.sum = &quot;function (x, y) { return x + y; }&quot;
&amp;gt;&amp;gt;&amp;gt; db.system_js.sum(3, 2)
5.0
&amp;gt;&amp;gt;&amp;gt; del db.system_js.sum
&amp;gt;&amp;gt;&amp;gt; db.system_js.sum(3, 2)
Traceback (most recent call last):
pymongo.errors.OperationFailure: [...] sum is not defined [...]&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The
&lt;a href=&quot;http://github.com/mongodb/mongo-python-driver/blob/master/pymongo/database.py#L587&quot;&gt;implementation&lt;/a&gt;
of the SystemJS class is actually pretty trivial. The trickiest bit is
getting the argument passing right between the Python lambda returned by
&lt;code&gt;*getattr*&lt;/code&gt; and the invocation of the stored JS function
within the eval.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>_Gluecon_ Early Bird _Discount_</title>
   <link href="http://dirolf.com/2010/03/30/gluecon-discount.html"/>
   <updated>2010-03-30T00:00:00+00:00</updated>
   <id>http://www.dirolf.com/2010/03/30/gluecon-discount</id>
   <content type="html">&lt;p&gt;I’ll be speaking at “Gluecon”:http://www.gluecon.com/2010/ in the end of May. The early bird pricing for registration ends on April 2nd, and you can get an additional 10% off of early bird registration as a reader of this blog if you use the code “&lt;code&gt;spkr12&lt;/code&gt;”!&lt;/p&gt;

&lt;p&gt;The conference looks to have a great lineup —
&lt;a href=&quot;http://dmerr.tumblr.com/&quot;&gt;Dwight&lt;/a&gt; will be speaking as well so there
will be a couple of members of the &lt;a href=&quot;http://www.10gen.com&quot;&gt;10gen&lt;/a&gt; team in
attendance. If you’re going to be at Gluecon let me know in the
comments. I look forward to seeing you there!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>A _New_ _GridFS_ Implementation for _PyMongo_</title>
   <link href="http://dirolf.com/2010/03/29/new-gridfs-implementation-for-pymongo.html"/>
   <updated>2010-03-29T00:00:00+00:00</updated>
   <id>http://www.dirolf.com/2010/03/29/new-gridfs-implementation-for-pymongo</id>
   <content type="html">&lt;p&gt;The API (Application Programming Interface) for
&lt;a href=&quot;http://api.mongodb.org/python&quot;&gt;PyMongo&lt;/a&gt;, the Python driver for
&lt;a href=&quot;http://www.mongodb.org&quot;&gt;MongoDB&lt;/a&gt;, has been pretty stable for quite some
time now. In general, I think that the driver does a great job of
exposing all of MongoDB’s functionality in a way that is both
MongoDB-ish and Pythonic (of course I’m biased — if you have suggestions
for improvements please let me know). There have been some minor tweaks
recently, like an improvement for the &lt;a href=&quot;http://api.mongodb.org/python/1.5.1%2B/api/pymongo/database.html#pymongo.database.Database.command&quot;&gt;command
API&lt;/a&gt;,
but there haven’t been any huge changes in a while.&lt;/p&gt;

&lt;p&gt;All that said, I think there is one place where PyMongo has been
deficient for a long time: its support for
&lt;a href=&quot;http://dochub.mongodb.org/core/gridfs&quot;&gt;GridFS&lt;/a&gt;. There are a couple of
problems with the GridFS implementation in previous versions (&lt;strong&gt;&lt;span style=&quot;text-align:left;&quot;&gt;= 1.5.2&lt;/span&gt;&lt;/strong&gt;) of PyMongo:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;It is slower and less concurrency-friendly than it needs to be.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;It could be much simpler and easier to work with.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;It allows some operations (modifying existing files) that are incorrect according to the GridFS semantics.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I think that all of these deficiencies stem from one fatal flaw in the
original API design: it was trying &lt;em&gt;too hard&lt;/em&gt; to mimic Python’s
filesystem API. Exposing file-like objects for writing and reading is
great, but things like focusing on filename as a file-handle (filename
is less important in GridFS) and allowing users to modify files (which
is not a concept supported by GridFS) were bad decisions. This post
introduces a new GridFS API for PyMongo which tries to address all of
the deficiencies in the old implementation.&lt;/p&gt;

&lt;h2 id=&quot;the-new-api&quot;&gt;The New API&lt;/h2&gt;

&lt;p&gt;The new GridFS API is available in PyMongo versions &lt;strong&gt;&lt;span style=&quot;text-align:right;&quot;&gt;= 1.6&lt;/span&gt;&lt;/strong&gt;. There are &lt;a href=&quot;http://api.mongodb.org/python/current/api/gridfs/index.html&quot;&gt;API
docs&lt;/a&gt;
available for the new version of GridFS, but this post walks through the
API in a little more detail.&lt;/p&gt;

&lt;p&gt;Almost all of the API is exposed through the GridFS class, here’s an
example instantiation:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-pycon&quot; data-lang=&quot;pycon&quot;&gt;&amp;gt;&amp;gt;&amp;gt; from pymongo import Connection
&amp;gt;&amp;gt;&amp;gt; from gridfs import GridFS
&amp;gt;&amp;gt;&amp;gt; db = Connection().test_database
&amp;gt;&amp;gt;&amp;gt; fs = GridFS(db)&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;You can also use an alternate root collection for GridFS by passing a
collection name as the second argument to &lt;code&gt;GridFS&lt;/code&gt;. Given an
instance of GridFS, creating new files and getting data from existing
ones is easy:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-pycon&quot; data-lang=&quot;pycon&quot;&gt;&amp;gt;&amp;gt;&amp;gt; file_id = fs.put(&quot;hello world&quot;)
&amp;gt;&amp;gt;&amp;gt; fs.get(file_id).read()
'hello world'&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The &lt;code&gt;put&lt;/code&gt; method takes a string or file-like object
containing data to be written to a GridFS file, and returns the
&lt;code&gt;\_id&lt;/code&gt; of the newly created file. It also accepts keyword
arguments for any of the fields available in the GridFS file spec. So to
insert the contents of the local file &lt;em&gt;myimage.jpg&lt;/em&gt; with the content
type “image/jpeg” and the filename “myimage” we would do:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-pycon&quot; data-lang=&quot;pycon&quot;&gt;&amp;gt;&amp;gt;&amp;gt; with open(&quot;myimage.jpg&quot;) as myimage:
...   oid = fs.put(myimage, content_type=&quot;image/jpeg&quot;, filename=&quot;myimage&quot;)
...&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The equivalent of doing this using the old API would be:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-pycon&quot; data-lang=&quot;pycon&quot;&gt;&amp;gt;&amp;gt;&amp;gt; from pymongo.objectid import ObjectId
&amp;gt;&amp;gt;&amp;gt; with open(&quot;myimage.jpg&quot;) as myimage:
...   with fs.open({&quot;filename&quot;: &quot;myimage&quot;,
...                 &quot;contentType&quot;: &quot;image/jpeg&quot;,
...                 &quot;_id&quot;: ObjectId()}, &quot;w&quot;) as grid_file:
...     grid_file.write(myimage.read())
...     oid = grid_file._id
...&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The &lt;code&gt;get&lt;/code&gt; method takes an &lt;code&gt;\_id&lt;/code&gt; of a file in
GridFS, and returns a file-like object (an instance of
&lt;code&gt;gridfs.grid\_file.GridOut&lt;/code&gt;) that can be used to read that
file’s data. If there is no file with the given &lt;code&gt;\_id&lt;/code&gt; an
exception is raised:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-pycon&quot; data-lang=&quot;pycon&quot;&gt;&amp;gt;&amp;gt;&amp;gt; oid = fs.put(&quot;hello world&quot;)
&amp;gt;&amp;gt;&amp;gt; fs.get(oid)
&amp;lt;gridfs.grid_file.GridOut object at ...&amp;gt;
&amp;gt;&amp;gt;&amp;gt; fs.get(&quot;non-existant _id&quot;)
Traceback (most recent call last):
gridfs.errors.NoFile: ...&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;To delete a file in GridFS, pass its &lt;code&gt;\_id&lt;/code&gt; to the
&lt;code&gt;delete&lt;/code&gt; method:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-pycon&quot; data-lang=&quot;pycon&quot;&gt;&amp;gt;&amp;gt;&amp;gt; fs.get(oid)
&amp;lt;gridfs.grid_file.GridOut object at ...&amp;gt;
&amp;gt;&amp;gt;&amp;gt; fs.delete(oid)
&amp;gt;&amp;gt;&amp;gt; fs.get(oid)
Traceback (most recent call last):
gridfs.errors.NoFile: ...&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;advanced-usage&quot;&gt;Advanced Usage&lt;/h2&gt;

&lt;p&gt;While &lt;code&gt;put&lt;/code&gt; should cover most use cases that opening a file
in write mode used to, there may be some cases where you don’t want to
write all of the file’s data at once. In that case you can use the
&lt;code&gt;new\_file&lt;/code&gt; method to get a new
&lt;code&gt;gridfs.grid\_file.GridIn&lt;/code&gt; instance which you can write to.
When you’re done with the instance call &lt;code&gt;close&lt;/code&gt; (or just use
Python 2.6’s &lt;code&gt;with&lt;/code&gt; statement to handle it for you). Like
&lt;code&gt;put&lt;/code&gt;, &lt;code&gt;new\_file&lt;/code&gt; takes keyword arguments for any
of the values in the GridFS file spec. A cool note about both methods is
that any unrecognized keyword arguments (in this example,
&lt;code&gt;location&lt;/code&gt;) will automatically be set as attributes on the
underlying file document:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-pycon&quot; data-lang=&quot;pycon&quot;&gt;&amp;gt;&amp;gt;&amp;gt; myfile = fs.new_file(location=[-74, 40.74])
&amp;gt;&amp;gt;&amp;gt; myfile.write(&quot;hello &quot;)
&amp;gt;&amp;gt;&amp;gt; myfile.write(&quot;world&quot;)
&amp;gt;&amp;gt;&amp;gt; myfile.writelines([&quot; and have a &quot;, &quot;good day!&quot;])
&amp;gt;&amp;gt;&amp;gt; myfile.close()
&amp;gt;&amp;gt;&amp;gt; out = fs.get(myfile._id)
&amp;gt;&amp;gt;&amp;gt; out.read()
'hello world and have a good day!'
&amp;gt;&amp;gt;&amp;gt; out.location
[-74, 40.740000000000002]&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Most of the examples above have been referencing files in GridFS by
their &lt;code&gt;\_id&lt;/code&gt;. The old API made more of a point of emphasizing
&lt;code&gt;filename&lt;/code&gt; as the primary mode of access. While the new API
encourages the better practice of referencing by &lt;code&gt;\_id&lt;/code&gt;,
there are still some cases where you might need to work with files based
on &lt;code&gt;filename&lt;/code&gt;, or where your application treats
&lt;code&gt;filename&lt;/code&gt; as a unique identifier.&lt;/p&gt;

&lt;p&gt;The way to work with filenames in the new API is to create a new GridFS
file with the same filename every time you need to modify a file. Since
files in GridFS store their upload date, we can always get the most
recent version of a file by filename. We can also reference by
&lt;code&gt;\_id&lt;/code&gt; to get any previous version — we can treat GridFS as a
versioned filestore. The method to get the last version of a file by
name is &lt;code&gt;get\_last\_version&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-pycon&quot; data-lang=&quot;pycon&quot;&gt;&amp;gt;&amp;gt;&amp;gt; a = fs.put(&quot;foo&quot;, filename=&quot;test&quot;)
&amp;gt;&amp;gt;&amp;gt; fs.get_last_version(&quot;test&quot;).read()
'foo'
&amp;gt;&amp;gt;&amp;gt; b = fs.put(&quot;bar&quot;, filename=&quot;test&quot;)
&amp;gt;&amp;gt;&amp;gt; fs.get_last_version(&quot;test&quot;).read()
'bar'
&amp;gt;&amp;gt;&amp;gt; fs.delete(b)
&amp;gt;&amp;gt;&amp;gt; fs.get_last_version(&quot;test&quot;).read()
'foo'&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;performance&quot;&gt;Performance&lt;/h2&gt;

&lt;p&gt;I’ve only done some very basic benchmarking of the new GridFS
implementation. It doesn’t appear to be a drastic improvement when
writing large files, but writing small files is about four times faster
in a simple benchmark of mine. This is because the simplification of the
API has reduced the per-file overhead dramatically. There are also huge
performance improvements when uploading a large file from disk or some
other file-like source (especially if it was being done naively using
the old API), as the new API automatically handles streaming from a
file-like source into chunk-sized buffers.&lt;/p&gt;

&lt;p&gt;Reading small files is about 10% faster with the new API, while there
doesn’t seem to be much difference with reading large files. A big
difference in performance for both reads and writes is that concurrency
is vastly improved. Since the GridFS semantics are handled correctly,
there is no longer a per-file lock for access - concurrent operations
are fully supported and safe now (with the notable exception of deleting
a file, which could cause concurrent readers to see partial data).&lt;/p&gt;

&lt;p&gt;If anybody has any ideas for benchmarks, or existing benchmarks for the
old API, I’d love to see how they compare — please leave a note in the
comments.&lt;/p&gt;

&lt;h2 id=&quot;deprecation-of-the-old-api&quot;&gt;Deprecation of the Old API&lt;/h2&gt;

&lt;p&gt;In the current state of the master branch I have removed the old GridFS
API completely, raising an &lt;code&gt;UnsupportedAPI&lt;/code&gt; acception when
attempts are made to use it. Normally I would go through a deprecation
window, but I’m considering just releasing like this. My reasoning is
that it’s a big change and I want people to be making it as soon as
possible. There is also a problem that mixed use of the APIs could be
unsafe (in general, &lt;em&gt;any&lt;/em&gt; use of the old API can be unsafe, if it’s used
to overwrite existing files). Let me know what your thoughts on this
decision are as well. Hoping to get this right as I think it will be a
big improvement to PyMongo!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>_pyporter2_</title>
   <link href="http://dirolf.com/project/pyporter2.html"/>
   <updated>2008-09-22T00:00:00+00:00</updated>
   <id>http://www.dirolf.com/project/pyporter2</id>
   <content type="html">&lt;p&gt;This “post” is actually just the &lt;strong&gt;pyporter2&lt;/strong&gt; homepage, reformatted as
a blog post. This is mainly so that the link doesn’t disappear on
anybody.&lt;/p&gt;

&lt;h2 id=&quot;about&quot;&gt;about&lt;/h2&gt;

&lt;p&gt;This is an implementation of the “Porter2 (english) stemming algorithm”:http://snowball.tartarus.org/algorithms/english/stemmer.html in Python. It was born out of some academic work I did on clustering algorithms in the spring of 2008. The “Porter Stemming Algorithm”:http://tartarus.org/~martin/PorterStemmer/ was first published in “this”:http://tartarus.org/~martin/PorterStemmer/def.txt 1979 paper - it is now one of the most widely known and used “stemming”:http://en.wikipedia.org/wiki/Stemming algorithms. An “implementation”:http://tartarus.org/~martin/PorterStemmer/python.txt of the Porter stemmer already existed in Python, but not of the updated Porter2 stemmer. I decided to implement a Python version of Porter2 as an exercise.&lt;/p&gt;

&lt;p&gt;Python bindings for the official C version of the Porter2 stemmer exist
&lt;a href=&quot;http://snowball.tartarus.org/wrappers/guide.html&quot;&gt;here&lt;/a&gt;. If using these
bindings is an option, it will probably be much more efficient than
using the pure Python implementation here. &lt;strong&gt;pyporter2&lt;/strong&gt; is useful when
the C bindings are not an option (like in
&lt;a href=&quot;http://www.jython.org/&quot;&gt;Jython&lt;/a&gt;,
&lt;a href=&quot;http://www.codeplex.com/Wiki/View.aspx?ProjectName=IronPython&quot;&gt;IronPython&lt;/a&gt;,
&lt;a href=&quot;http://github.com/babble/babble&quot;&gt;Babble&lt;/a&gt; or &lt;a href=&quot;http://code.google.com/appengine/&quot;&gt;App
Engine&lt;/a&gt;).&lt;/p&gt;

&lt;h2 id=&quot;download&quot;&gt;download&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;pyporter2&lt;/strong&gt; is open source software, released under an MIT-style
license. The latest version of &lt;strong&gt;pyporter2&lt;/strong&gt; is available
&lt;a href=&quot;http://github.com/mdirolf/pyporter2&quot;&gt;here&lt;/a&gt;. To check out the source,
install &lt;a href=&quot;http://git.or.cz/&quot;&gt;Git&lt;/a&gt; and run:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git clone git://github.com/mdirolf/pyporter2.git&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;usage&quot;&gt;usage&lt;/h2&gt;

&lt;p&gt;The new API (Application Programming Interface) matches that of
&lt;a href=&quot;http://snowball.tartarus.org/wrappers/guide.html&quot;&gt;PyStemmer&lt;/a&gt;. Here is
an example of how to use &lt;strong&gt;pyporter2&lt;/strong&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-pycon&quot; data-lang=&quot;pycon&quot;&gt;&amp;gt;&amp;gt;&amp;gt; import Stemmer
&amp;gt;&amp;gt;&amp;gt; print Stemmer.algorithms()
['english']
&amp;gt;&amp;gt;&amp;gt; stemmer = Stemmer.Stemmer('english')
&amp;gt;&amp;gt;&amp;gt; print stemmer.stemWord('cycling')
cycl
&amp;gt;&amp;gt;&amp;gt; print stemmer.stemWords(['cycling', 'cyclist'])
['cycl', 'cyclist']
&amp;gt;&amp;gt;&amp;gt; print stemmer.stemWords(['cycling', u'cyclist'])
['cycl', u'cyclist']&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;testing&quot;&gt;testing&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;pyporter2&lt;/strong&gt; includes a test suite written using
&lt;a href=&quot;http://docs.python.org/lib/module-unittest.html&quot;&gt;unittest&lt;/a&gt;. To run the
tests, do:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;python Stemmer.py&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;questions&quot;&gt;questions&lt;/h2&gt;

&lt;p&gt;Feel free to leave a comment with any questions. It’d also be cool to
let me know if you find &lt;strong&gt;pyporter2&lt;/strong&gt; useful for anything.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>_Zoomix_ -- Another _JavaScript Game_</title>
   <link href="http://dirolf.com/2007/11/zoomix-another-javascript-game.html"/>
   <updated>2007-11-30T00:00:00+00:00</updated>
   <id>http://www.dirolf.com/2007/11/zoomix-another-javascript-game</id>
   <content type="html">&lt;script src=&quot;/javascript/zoomix.js&quot; type=&quot;text/javascript&quot; charset=&quot;utf-8&quot;&gt;
&lt;/script&gt;

&lt;p&gt;Updated 2009-12-13: Adding the actual game itself to this page, mainly
so that Aaron has a place to play.&lt;/p&gt;

&lt;p id=&quot;MD-Text&quot;&gt;
&lt;span id=&quot;MD-GameOver&quot;&gt;GAME OVER - Press Spacebar to Restart&lt;/span&gt;
Score: &lt;span id=&quot;MD-Score&quot;&gt;0&lt;/span&gt;

&lt;/p&gt;
&lt;canvas id=&quot;MD-Canvas&quot; width=&quot;600&quot; height=&quot;600&quot;&gt;
The game would be here if you were using a browser that supported the
[canvas
tag](http://www.whatwg.org/specs/web-apps/current-work/#the-canvas-element&lt;/canvas&gt;
&lt;p&gt;)&lt;/p&gt;

&lt;p&gt;Yesterday I wrote another game using JavaScript and the canvas tag, which I’ve named &lt;em&gt;Zoomix&lt;/em&gt;. This time the design of the game is completely original, and I think it came out pretty nicely. Hopefully you should be able to figure out the rules / object of the game after playing with it for a few minutes. Let me know what you think! (And post your high scores in the comments).&lt;/p&gt;

&lt;p&gt;The look and feel of the game was inspired by the &lt;a href=&quot;http://www.rubiks.com/&quot;&gt;Rubik’s
Cube&lt;/a&gt;. After creating a static image of a face
of the cube, zooming in on it seemed to be the only logical thing to do.
After that was implemented, the mechanics of gameplay just fell out.&lt;/p&gt;

&lt;p&gt;The game is &lt;a href=&quot;http://github.com/mdirolf/zoomix&quot;&gt;open-source&lt;/a&gt; (but those
of you who care probably viewed the source already).&lt;/p&gt;

&lt;p&gt;See also: &lt;a href=&quot;/2007/06/fun-game.html&quot;&gt;MDCave&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Enabling _Cross-Domain AJAX_ in _Firefox_</title>
   <link href="http://dirolf.com/2007/06/enabling-cross-domain-ajax-in-firefox.html"/>
   <updated>2007-06-11T00:00:00+00:00</updated>
   <id>http://www.dirolf.com/2007/06/enabling-cross-domain-ajax-in-firefox</id>
   <content type="html">&lt;div class=&quot;note&quot;&gt;
Updated 2009-12-13: This post seems to be the most popular of those from
the old incarnation of this blog. As such I’ve decided to migrate it
over. Unfortunately I can’t migrate the comments as well. One comment
which seems that it might be useful comes from
[stefano](http://myblog.digitalemagine.com/) (I’ve editorialized
somewhat):

&amp;gt; Good trick, but there’s an easier way to enable cross domain without
&amp;gt; editing config files by hand. Type “about:config” in your URL bar,
&amp;gt; then right click on the list of preferences and select the *New* -&amp;gt;
&amp;gt; *String* contextual menu. Add
&amp;gt; **capability.policy.default.XMLHttpRequest.open** as key name and
&amp;gt; **allAccess** as value. I do not remember if this is taken into
&amp;gt; account immediately or if you have to reboot. Done!

I’m also not positive if this works in newer versions of Firefox, and I
haven’t tested it. Feel free to let everybody know in the comments.

&lt;/div&gt;
&lt;p&gt;Tonight I have finally conquered one of the biggest annoyances of the past year for me (in terms of development at least). Developing web applications with Firefox is a pleasure because of the “firebug extension”:http://getfirebug.com/. Nothing comes close in Safari. Unfortunately, Firefox doesn’t allow cross-domain XMLHttpRequests for security reasons. While good security is a plus, this restriction can make development and testing a real chore. For those of us willing to risk the security vulnerability, here is how to bypass the cross-domain restriction once and for all.&lt;/p&gt;

&lt;p&gt;#&lt;/p&gt;

&lt;p&gt;
Close Firefox

\#

&lt;p&gt;
Edit the file **prefs.js** in your Firefox user profile folder

\#

&lt;p&gt;
Add the following line anywhere in the file:  

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;user_pref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;capability.policy.default.XMLHttpRequest.open&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;allAccess&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;


\#

&lt;p&gt;
Save the file and re-open Firefox. You can now risk your life and limb
by doing XHR (XMLHttpRequests)’s to whatever domains you want -
congratulations!
&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>_MDCave_ -- A _JavaScript Game_</title>
   <link href="http://dirolf.com/2007/06/fun-game.html"/>
   <updated>2007-06-07T00:00:00+00:00</updated>
   <id>http://www.dirolf.com/2007/06/mdcave</id>
   <content type="html">&lt;script src=&quot;/javascript/mdcave.js&quot; type=&quot;text/javascript&quot; charset=&quot;utf-8&quot;&gt;
&lt;/script&gt;

&lt;p&gt;Updated 2009-12-13: Adding the actual game itself to this page, mainly
so that Aaron has a place to play. Also changing the title to &lt;strong&gt;MDCave —
A JavaScript Game&lt;/strong&gt; from &lt;strong&gt;A Fun Game&lt;/strong&gt;.&lt;/p&gt;

&lt;p id=&quot;MD-Text&quot;&gt;
&lt;span id=&quot;MD-GameOver&quot;&gt;GAME OVER - Press Spacebar to Restart&lt;/span&gt;
Score: &lt;span id=&quot;MD-Score&quot;&gt;0&lt;/span&gt;

&lt;/p&gt;
&lt;canvas id=&quot;MD-Canvas&quot; width=&quot;800&quot; height=&quot;600&quot;&gt;
The game would be here if you were using a browser that supported the
[canvas
tag](http://www.whatwg.org/specs/web-apps/current-work/#the-canvas-element&lt;/canvas&gt;
&lt;p&gt;)&lt;/p&gt;

&lt;p&gt;In lieu of a real post here’s a time-waster for those I haven’t showed already. This is a game I wrote to procrastinate about a month or two ago, meant to be a larger version of “this game”:http://www.sfcave.com/javaCave.php. It should work in Safari and Firefox. Also, cut me some slack for the lack of polish, as it really was a one night affair. The whole thing is written using Apple’s canvas tag and JavaScript, feel free to use the “source”:http://github.com/mdirolf/mdcave for whatever you want. Post your high scores in the comments.&lt;/p&gt;

&lt;p&gt;See also: &lt;a href=&quot;/2007/11/zoomix-another-javascript-game.html&quot;&gt;Zoomix&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 

</feed>
