Mongo Just Pawn in Game of Life

This is in response to this nifty blog post on storing a chess board in MySQL and this snarky Tweet about NoSQL DBs (because I’m never snarky).

On the one hand, I can’t believe I’m doing this. What database can’t store a chessboard? On the other hand, it’s fun, and once I thought of the title, I really had to write the post. Let the pointless data storage begin!

Okay, so first we need a representation for a chess piece. I’m tempted to just use the UTF-8 symbol and position, but it would be nice ot have a human-readable string to query on. So, we’ll use something like:

    "name" : "black king",
    "symbol" : "♚",
    "pos" : [8, "e"] 

Ha! Can your relational database query for a subfield of a subfield of type integer or string? (Actually, I have no idea, maybe it can.) Anyway, moving right along…

So, MongoDB can just run JavaScript, so I’ll write a JavaScript file that does everything we need. Here’s the code to create the basic chess board. “db” is a global variable that is the database you’re connected to. It defaults to “test”, so we’ll start by switching it to the “chess” database. If it doesn’t exist yet, it’ll be created when we put something in it. Then we’ll actually populate it:

// use the "chess" database, creates it if it doesn't exist
db = db.getSisterDB("chess");
// make sure the db is empty (in case we run this multiple times)

// map indexes to chess board locations
column_map = {0 : "a", 1 : "b", 2 : "c", 3 : "d", 4 : "e", 5 : "f", 6 : "g", 7 : "h"};
// starting at 1a
color_char = {"black" : "█", "white" : " "};
color = "black";
for (i=1; i<=8; i++) {
    for(j=0; j<8; j++) {
        db.board.insert({x : i, y : column_map[j], color : color_char[color]})
         * switch the color of the square... it's always the opposite
         * of the previous one, unless we're at the end of a row
        if (j != 7) {
            color = color == "white" ? "black" : "white";

Okay, now let’s iterate through the pieces, create their objects, and add them to the board:

// create unique ids from symbols
function get_name(symbol, column) {
    switch (symbol) {
    case '♖':
    case '♜':
        return " rook " + (column < 4 ? "left" : "right");
    case '♘':
    case '♞':
        return " knight " + (column < 4 ? "left" : "right");
    case '♗':
    case '♝':
        return " bishop " + (column < 4 ? "left" : "right");
    case '♕':
    case '♛':
        return " queen";
    case '♔':
    case '♚':
        return " king";
    case '♙':
    case '♟':
        return " pawn " + column;

// go through the 2D array of pieces, create the objs, and insert them
function add_pieces(color, color_str) {
    for (row=0; row<color.length; row++) {
         chess_row = row + (color_str == "white" ? 1 : 7);

         for (column=0; column < color[row].length; column++) {
             chess_column = column_map[column];
             db.board.update({x : chess_row, y : chess_column}, {$set : {piece : {name : color_str+get_name(color[row][column], column), symbol : color[row][column], pos : [chess_row, chess_column]}}});

add_pieces([['♖','♘','♗','♕','♔','♗','♘','♖'], ['♙','♙','♙','♙','♙','♙','♙','♙']], "white");
add_pieces([['♟','♟','♟','♟','♟','♟','♟','♟'], ['♜','♞','♝','♛','♚','♝','♞','♜']], "black");

Phew! The hard part is done. Let’s print out this sucker!

// sort by x from 8-1 and y from a-h
cursor = db.board.find().sort({x:-1, y:1});

count = 0;
board = "";
while(cursor.hasNext()) {
    square =;
    if (square.piece) {
        board += square.piece.symbol;
    else {
        board += square.color;

    if (count % 8 == 0) {
        board += "n";

And we get:

 █ █ █ █
█ █ █ █ 
 █ █ █ █
█ █ █ █ 

Very snazzy. Now we can query by symbol, human readable name, or board position. Also, it’ll only take two updates to move a piece. (I attached chess.js, if you don’t want to copy/paste it yourself.)

Public Speaking: The Prequel

Me, presenting at SF JUG
Me, presenting at SF JUG

There’s a video that everyone seems to have seen of me (seriously, when I went to Brazil everyone mentioned it) presenting MongoDB to the San Francisco Java User Group.  Unfortunately, I think it’s the worst presentation I’ve ever given, partly because of the lead-up and partly because of inexperience.

I looked up directions and gave myself an extra 15 minutes to get to the talk.  It looked like I had to take a bus so I walked down to the bus stop, but all the buses that went by had a different naming scheme than what I had to take.  I asked the driver on the next bus that went by and he pointed downwards and drove off, which I realised a second later probably meant that I wanted the subway.  Whoops.

I went downstairs and saw ticket machines, so I went over and bought tickets.  Then I went over to the gate, which didn’t seem to take tickets.

“Excuse me,” I said to the guard, “how do I get in?”

“Oh, that’s a BART ticket, this is the Muni system, it takes quarters.”

So I had to wait in line at the ticket/change machines again, because I didn’t have eight quarters on me.

I finally made it to a platform and the stupid Muni came.  I had to go two stops.  At the second stop I got out, went upstairs, exited the station and… had no idea where I was.  I had somehow gotten off at the wrong station.  I started to freak out.  However, San Francisco is a city, and as a city, it has cabs.  I gave up on public transportation and hailed a cab.  The driver drove me all of five blocks to the building where the Java User Group was meeting.  I handed him the rest of the money in my wallet and ran in.

By the time I got there, I was at least five minutes late.  However, there were thirty people waiting to sign in, so I relaxed a bit as I waited in line.

The organiser looked relieved when he saw me and pulled me and the other presenter aside.  We were supposed to each talk for an hour and hold all questions until the end.  I was up first and started in. With about two slides to go, I casually checked my cellphone to see if I was on track with the time.  I wasn’t.

I had been talking for 25 minutes.

I must have looked like I had suddenly been hit by a bus.  In the video, you can see me suddenly run my hand through my hair about 16 times (I didn’t even realise I did that when I was nervous).  Then I made those two slides last as long as I damn well could, which was about 10 minutes.

When people were done asking questions, I skulked to the back of the room where I found a seat on the edge.  After a few minutes, I couldn’t take it anymore, so I went to the bathroom where I could freak out in peace.  When I got back, I sat down and tried not to think about my talk.  And, after about ten minutes, the other speaker wrapped up his talk.  It seemed like he had just started, but I assumed trauma had made time go all squiggly.  I checked my cellphone, and indeed, he had only talked for a half-hour, too!  I had died a thousand deaths for nothing.

Afterwards, I talked to a bunch of cool people who were working on interesting projects, which was definitely the highlight.  Once all the people who wanted to talk had gone, I packed up and left.  There was a bus that could take right to my hotel that I was right on time to catch.  I walked towards the stop and, as I approached, I heard the bus turn the corner behind me.  I was ahead of it, but it gained speed on the straightaway.  It was a long block, and it got a couple-hundred yard lead before it stopped to pick up passengers at the end of the block.  I went into full speed, sprinting down the street with my damn brick of a laptop.  The bus was stuck at the stop, as the traffic light ahead of it was red.  Hurrah!  I covered the last fifty yards, touched the back of the bus, and… the light turned green and the bus drove off.

I.  Was.  So.  Pissed.

I decided that I’d walk back to the hotel, since I now vaguely knew where I was.  It was a half-hour walk, but I was done with San Francisco public transportation.

When I got home, I realised it was just as well that the bus had driven off, because I didn’t even have a dollar left in my wallet after paying for the Bart ticket, Muni quarters, and taxi ride.

NoSQL Trolls

trollI have a Twitter feed for the term “nosql” and every day I get tweets like:

“What moron came up with #nosql?  you’re all fired!”

“nosql is making all the same mistakes people made 40 years ago… relational dbs won!”

“yeah, use nosql… if you don’t mind losing all your data”

(these are based on real tweets, but aren’t actually verbatim.  They’re all pretty much the same.)  I hope I meet someone who says this to me someday, though, so I can say: “Boy, what a good point!  If only Google and Yahoo and LinkedIn and Twitter and the thousands of other high-traffic websites had listened to you.  Obviously you know what’s going on better than they do, this NoSQL thing is just a bunch of idiots spinning their wheels.”

Then, as they reeled, rendered helpless by my cunning sarcasm, I’d continue in a slightly different vein: “You freakin’ moron!  Relational databases failed miserably for huge websites, so alternative database popped up to fill that need.  And, so long as we’re making a new database, we figure computer languages and database administration have changed a bit since 1974, so we might as well make dbs easier to use.  You’re welcome!”

Then I’d punch them in gibblies until they saw my point.

I might need a vacation.

Public Speaking

MongodbI talked at LILUG (Long Island Linux User Group) about MongoDB on Tuesday, which was really fun.

Not that it started out all that well. One of LILUG’s officer’s picked me up at the station. We had… an imperfect fusion of souls. He told me, on the way to the pub, that he was sick of GNU, sick of Linux, and sick of being an officer in LILUG. When we got to the pub, he made a joke about Chinese people having slanty eyes. Ugh.

Anyway, we got there, and met a couple guys standing at the bar. The older one (~60) asked if he could buy me a drink, to which I awkwardly acquiesced. I’m never sure what the protocol is, if there’s anything implied by accepting a drink. The other guys wandered off towards a table, but the old guy made no move.

“Um, are you… um… a member of LILUG?” I asked.

“No,” he said, staring at me. Whoops.

“Um, I have to go,” I said, and went over to the table where the LILUG guys had gone.

“Yeah, he’s just some random guy who was at the bar,” one of the members said, laughing. Har de har.

I ordered nachos, which turned out to be a freakin mountain that could have served six people. They were seriously piled almost a foot high on the plate. They were delicious, and a bunch of really nice LILUG members showed up.

Once we were done eating, we went over to Stony Brook, which is where I was actually giving my talk. I’ve had a cold for the last week and I was a bit nervous about my voice giving out, but it held up and people really seemed to enjoy it.

I like it when people ask lots of questions an participate, and I had a brainwave before I left the office on how to encourage it. When I started my presentation, I told people to feel free to ask questions. “And the first person who asks a question,” I said, rooting around in my bag, “gets this fabulous Mongo mug!” I told them, unearthing it and holding it up. A college student’s hand shot up. “What was Mongo named after?” he asked. And we were off to the races!

Afterwards, everyone went out for one more drink. “To the downfall of SQL!” someone called, and everyone cheered and toasted to it.

P.S. Just to be clear, I didn’t actually advocate the downfall of SQL, in fact, I specifically mentioned relational databases are needed in some cases. It was cute, though 🙂

P.P.S. Slides are on slideshare.

Installing Linux on a MacBook Air

fffffffuuuuuuuuIt’s not a clean victory, but I got Linux onto my MacBook Air.

When I first got my Air, I launched the Ubuntu install disk and followed the instructions on the Ubuntu wiki. Unfortunately, these instructions are apparently for the MacBook Air 1,1, and I had a MacBook Air 2,1. The Linux kernel froze in the middle of initializing.

After a couple, ahem, weeks of playing around with kernel parameters, I got it to a point where I realized it was Ubuntu, not Linux, that was screwing up, so I decided to try some other distro. I got a Debian network install CD (the full install is 31 CDs!) and tried it. It booted into the installer fine, and started merrily installing the system. I suddenly realized I had a doctor’s appointment, and had a terrible premonition that, by the time I got back, something would have gone wrong.

My premonition was correct. When I returned, the CD had stopped working. I checked it for errors, and it was fine. However, every time I started the computer now, the CD driver would make an ominous clicking noise and pop open. If I held it closed, it would make a downright alarming snapping noise. And reFit couldn’t even recognize it.

So, I installed VMWare Fusion on the Mac partition, and installed Linux on that. I’m trying to look on the bright side: I get OS X power management, wireless, and sound with a Linux environment.

Five Worst Places for Mosquito Bites

If there is a mosquito within 50 feet of me, it will find me and bite me.  I am one of those people that attracts them like a magnet.  A delicious, blood-filled magnet.  Anyway, these are the places you should avoid getting bitten:

1. Face – Could be forhead, nose, cheek, eyelid… they all look like zits and itch like hell.  I always get these when there’s a mosquito in my bedroom, since the rest of me is under the covers all night.

2. Top joint of finger – these itch a lot, and then they just hurt because there’s not really enough skin slack there to support something swelling up.

3. Nipple – very difficult to itch.  Looks strange, too.

4. Big toe – there’s juuuust enough room between your foot and the shoe to rub this all day, but have you ever tried itching your foot through a shoe?

5. Rows of bug bites – okay, this last one isn’t really a place, but I’ve gotten these really irritating bites where the mosquito bit me, took two steps, bit me, took two steps, bit me, and so on.  It’s like the poison ivy of bug bites.

In conclusion, I hate mosquitoes.

Foz do Iguacu

I just arrived in Brazil for Latinoware.  I didn’t know what the weather would be like, so I packed everything from tank tops to long sleeves.  Turns out it’s totally tropical.  It started pouring a bit after we arrived, and it’s like a typhoon out there.  It’s still 90 degrees, though.  I’ll need to pick up some more tank tops, I think.

Replacing $ in the MongoDB PHP Driver

I’ve just added a feature to the Mongo PHP driver (and I plan to add it to the Perl driver soon) to use a character other than $ for special ops.

In Mongo, there are tons of interesting things you can do by using $-prefixed strings:

// run a server-side function as part of a query
db.collection.find({$where : function() { ... });

// increment a field in an update
db.collection.update({_id : id}, {$inc : {counter : 1}});

// add more cowbell to an array
db.collection.update({_id : id}, {$push : {life : "cowbell"}});

There are a gazillion more, and we keep adding them. Anyway, it’s a bit of a pain in PHP (and Perl) because “$var” means “replace $var with the variable $var and convert it to a string.” As there is probably no $var variable, it’s null, and null converted to a string is “”. So, instead of the string “$var”, you get “”. Of course, you can prevent this by saying “$var” or ‘$var’ (single quotes), but people have requested being able to use a different character, instead of $.

I considered choosing one for people, but then I decided it was better to let people choose their own. So, if you want to use the character with the ASCII value of 0, go nuts (anyone who maintains your code certainly will).

To choose an alternative, add a line to your php.ini file:

mongo.cmd = "+"

…replacing “+” with whatever symbol you’d like to use. If you do not have access to your php.ini file or you feel like being a jerk (I think doing this makes your code pretty impenetrable), you can change it anywhere in your code with ini_set:

// use : for an update (instead of $inc)
ini_set("mongo.cmd", ":");
$collection->update(array("_id" => $id), array(":inc" => array("counter" => 1)));

// use > (instead of the $cmd collection)
ini_set("mongo.cmd", ">");
$cmdCollection = $db->selectCollection(">cmd");
$cmdCollection->findOne(array("getlasterror" => 1));

// use x for db refs (this is a particularly bad idea, use a character that 
// won't occur as the first character of a key name)
ini_set("mongo.cmd", "x");
$collection->insert(array("ref" => array("xref" => $ns, "xid" => $id)));

My recommendation is to decide on an alternative character and stick with it.

Some technical details:

  • $ will still work. Even if you choose another character, you can still use $s, too.
  • Only the first character will be replaced by $. So, if you chose “~” as your substitute character, “~~~” would be sent to the database as “$~~”.
  • I made this work in all of the places I could think of where you’d need a $ (key names, database references, and collection names). If you think of any others, please let me know so I can add them

Testing MongoDB Replica Pairs with Perl

I was just fixing this, and it’s a pain to setup/test, so I figured I’d put up what I did here, so at least I’d never have to figure it out again.  So, start two db servers and an arbiter:

$ mkdir ~/data1
$ mkdir ~/data2
$ ./mongod --pairwith localhost:27018 --arbiter localhost:27019 --dbpath ~/data1
$ ./mongod --port 27018 --pairwith localhost:27017 --arbiter localhost:27019 --dbpath ~/data2
$ ./mongod --port 27019 #arbiter

Then kick off the following Perl script:

use strict;
use warnings;
use Carp;
use Data::Dumper;

use MongoDB;

# order of left_host/right_host is unimportant
my $conn = MongoDB::Connection->new('right_host' => 'localhost', 'left_host' => 'localhost', 'left_port' => 27018);

my $db = $conn->get_database('x');
my $coll = $db->get_collection('y');


for (my $i=0; $ifind_one;

    print $@."n";

    sleep 1;

Now, you’ll start getting stuff like:


That means everything is okay. Now, kill the first mongod process that you started. (The first one you started is probably master. If you don’t see a “pair: setting master=1 was 0” on the other one after a couple seconds, restart the first one and kill the second one.) You’ll notice your output changes to:

finding...couldn't find master at /usr/local/lib/perl5/site_perl/5.10.0/i686-linux/MongoDB/ line 177.
finding...couldn't find master at /usr/local/lib/perl5/site_perl/5.10.0/i686-linux/MongoDB/ line 177.
finding...couldn't find master at /usr/local/lib/perl5/site_perl/5.10.0/i686-linux/MongoDB/ line 177.

The slave hasn’t become master yet, so there’s nothing the db can use (there will probably be a 2-10 second delay before the slave becomes master). Once you see “pair: setting master=1 was 0” scroll by on your db logs, you’ll notice the Perl script’s output change back to:


You can go back and forth, killing off master dbs and restarting them.

Final Days in CA

I was reading my new book about the actress in rehab, and I was vaguely wondering why the writer’s name sounded familiar.  I couldn’t quite place it, so I flipped to the back to see what her bio said.  Suddenly I realized where I knew her from.

“Hey Andrew, guess who wrote this book?”  I showed him the front cover.

“No!  No way!  THE Carrie Fisher?”

Yup.  My book was written by Princess Leia.  It wasn’t great, but it wasn’t terrible, either.  Now I’m wondering if I should get another book.  We’re flying home tomorrow, but I feel vaguely uncomfortable going even 24 hours without something to read.

Speaking of going home, I mailed all of our dirty clothes home today so that we’ll have almost nothing to carry tomorrow.  I asked the front desk, and they told me the nearest post office was in the back of Macy’s.  I walked down the Macy’s block and back again.  It was a whole block of Macy’s, nothing else.  Finally, I asked at a restaurant.

“The post office is inside Macy’s.”

Weird.  I went into Macy’s, where there was no sign of a post office.  I asked an over-collagened makeup hawker where the post office was.  “Oh, in the basement.”

I went down the escalator, wandered around for a bit, and finally gave up and asked another sales lady.  “If you follow the red wall, it’s down there.”  Oh.

So, to get to the post office, you go into Macy’s, go down to the basement, make a U-turn, and it’s in sort of a back room.  I’ve been to speakeasies that were easier to find.