Node Knockout, the world’s biggest, baddest node.js hackathon, is back. This will be the 4th year in a row, and we’re looking to make this one the biggest and best yet!

What is it?

You and (up to) 3 of your closest friends compete against developers all over the world in a 48 hour race to build the best node app. See the rules.

Winners get prizes and glory.

Sign me up!

Not so fast cowboy! The competition starts Nov 9 at 0:00 UTC (local times vary). Registration opens Tues, Sept 17.

Join our email list to be alerted when spots are available.

Are you fired up?

We’re fired up! Let’s get ready to rumble!

Looking to sponsor? Want to judge instead of compete? Let us know.

We’re excited to announce the winners of Node Knockout! Here are the champions among the 167 entries submitted this year.

Overall Team

Disasteroids

by SomethingCoded

Disasteroids is a game where you do battle among a series of asteroids, slinging missiles at other players through the gravity field and trying to hit the most exciting shots. Inspired by the classic artillery games of old and our universal fascination with the stars.

Overall Solo

HashPay

by DoTheJoy

Tweet payments to your friends.

Innovation

Node.js Christmas Sweater

by Coalition for the Liberation of Itinerant Tree-Dwellers

It’s a hardware/software hack. We created a wireless sweater that takes in messages from the internet and wirelessly displays them on our LoL Shield powered by an arduino built into our own handmade christmas sweater. Watch the video.

Design

Hex

by Public Class

A multiplayer game where being in the way of your opponents puts you on top.

Utility / Fun

Narwhal Knights

by 🍉

Narwhal Knights is a game of knights. Riding Narwhals. Narwhals with wings. Impale the other knights while dodging deadly spikes and lava balls of doom.

Completeness

Asciigram

by comorichweb

Convert your webcam and images to ASCII and share them!

Popularity

Space bridge

by Design 4 Quality

A devastating earthquake has hit our planet! In these situations, help is needed by most! While the majority is trying to help the people, animals and the plant world, You have got a special mission to find those of whom a very small number of people know exist…Aliens!!

Congratulations!

Congratulations to all who participated. There were a ton of great entries this year!

We will be following up over email with winners and sponsors that are providing prizes.

Here’s a quick tip: your entry should link to your team’s page so you can get as many votes as possible.

Alternatively, if you want to let people vote directly from your app, you can use our Vote KO widget:

Vote KO widgets

Here’s how to use it:

<iframe src="http://nodeknockout.com/iframe/YOUR_TEAM_SLUG" frameborder=0 scrolling=no allowtransparency=true width=115 height=25>
</iframe>

You can find your YOUR_TEAM_SLUG on your team’s page. The slug is the last segment of the url (e.g. http://nodeknockout.com/teams/fortnight-labs).

Overview

Apigee App Services is a hosted cloud service to store, retrieve & query your data — and so much more. Create a user record in our database and boom — we automatically give you a method to let that user sign-in to the service (using OAuth), let him own other pieces of data, post stuff to his activity wall, and the ability to become friends & share data with other users — without you having to write a single line of code. Want to store arbitrary data (cats, dogs, cars, songs, …)? If you can express it as JSON, we can store it! We also offer geoindexing and geoqueries out of the box, sign-in with Facebook, automatic full-text querying (with a SQL-compatible language), file upload in a single call (images, videos, songs, etc.) and lots more!

Here’s how to get started with Apigee App Services and Node.js!

Installing

To install the Usergrid Node.js SDK, use the NPM:

$ npm install usergrid-sdk

Or visit the github repo:

https://github.com/apigee/usergrid-node-js-sdk

Getting started

To get you started, please note that the SDK consists of one main JavaScript file, located in the project at:

/lib/usergrid-sdk.js

Simply include the SDK to begin to use it:

var sdk = require('usergrid-sdk');

Then initialize it with your app and org id:

sdk.ApiClient.init('apigee', 'nodejs');

You are now ready to use the sdk handle to make calls against the API. For example, you may want to set your client id and Secret:

sdk.ApiClient.setClientSecretCombo('b3U6y6hRJufDEeGW9hIxOwbREg', 'b3U6ZOaOexFiy6Jh61H4M7p2uFI3h18');

If you are using the client secret and id, you will also want to enable that (client) authentication method:

sdk.ApiClient.enableClientSecretAuth();

Entities and Collections

Entities and Collections are used to model the custom data you need to store in your app. To enable you to use these in your app, the Node SDK provides the Entity and the Collection objects. The following sections describe how to create and use these objects and show examples from a sample app about dogs.

The Entity Object

Start by creating a new Entity object, where the argument is the name of the collection that the entity will be part of. In the Dogs sample app, here is how a new dogs entity is created in a collection named dogs:

var dog = new sdk.Entity("dogs");

Next, add any needed custom fields. For example:

dog.set("name","Dino");
dog.set("owner","Fred");
dog.set("state","hungry");

After the object is complete, save it back to the API, for example:

dog.save();

When the entity is saved, the API gives it a UUID that uniquely identifies the entity in the database. This UUID is stored in the Entity object and will be used for any future calls to the API. This ensures that the correct entity is updated. For example, the UUID is used if the object is updated and needs to be saved again:

dog.set("state", "fed");
dog.save(); //updates the same dog entity as before

Or, if the entity is changed in the database (perhaps by another user of your app), and needs to be refreshed:

dog.fetch(); //will only work if the UUID for the entity is in the dog object

In this way, multiple clients can update the same object in the database.

If you need to get a property from the object, call the get() method and provide the property as an argument to the method, for example:

var state = dog.get("state");

If you no longer need the object, call the destroy() method. This deletes the object from database. For example:

dog.destroy(); //no real dogs were harmed!

Although the object is deleted from the database, it remains in your program. Destroy it if needed by setting it to a null value, for example:

dog = null; //no real dogs were harmed!

The Collection Object

The Collection Object models the custom collections you create using the API. Collections organize entities. For example, you could create a collection called “dogs”. Then, you can add “dog” entities to it.

To get started, create a new Collection object, where the argument is the type of collection you intend to model. For example:

var dogs = new sdk.Collection('dogs'); //makes a new 'dogs' collection object

If your collection already exists on the server, call the get() method to populate your new object with data from the server. For example:

dogs.get();

By default, the dogs.get() method uses the API to retrieve the first 10 dog entities and loads them into the dogs Collection object. If you want to add a new entity to the collection, simply create it. For example:

var dog = new sdk.Entity("dogs");
dog.set("name","fido");

Then add it to the collection (and save it to the API):

dog.addNewEntity(dog);

Note: The addNewEntity() method adds the entity to the collection and also saves it to the API. If you have already saved an entity, you can simply call the addEntity() method.

So this:

var dog = new sdk.Entity("dogs");
dog.save();
dogs.addEntity(dog); //entity is added only

Is equivalent to this:

var dog = new sdk.Entity("dogs");
dogs.addNewEntity(dog); //entity is added and saved

Displaying Results

After you populate your Collection object, you can display a list of all the entities currently stored in the Collection object. Here’s how it’s done in the Dogs app:

//iterate through all the items in this "page" of data
while(dogs.hasNextEntity()) {
    //get a reference to the dog
    var dog = dogs.getNextEntity();
    //do something with the next dog in the list
    //value is in dog.get('name');
}

Note: This code snippet only loops through the items currently stored in the Collection object. If there are more entities in the database that you want to display, either use paging, or a custom query.

Custom Queries

A custom query allows you to tell the API that you want your results filtered or altered in some way. The following example specifies that the query results should be ordered by creation date:

dogs.setQueryParams({'ql':'order by created DESC'});

If you also wanted to get more entities in the result set than the default 10, say 100, you can specify a query similar to the the following (the limit can be a maximum of 999):

dogs.setQueryParams({'ql':'order by created DESC','limit':'100'});

There are many cases where expanding the result set is useful. But be careful - the more results you get back in a single call, the longer it will take to transmit the data back to your app.

You can find more information on custom queries here:

http://apigee.com/docs/usergrid/content/queries-and-parameters

Learn More

We have a full README for our SDK with more examples, explanations on how to use advanced features like user management, access other endpoints and a sample app you can clone.

Signing up & Getting Help during the KO

To sign up during the knockout, please go here.

We also have full service docs.

If you need any help during the weekend, you can ping Rod on IRC (rockerston in #nodeknockout on Freenode) GTalk (rsimpson@apigee.com), email (rsimpson@apigee.com) or Skype (rockerston).

We are also currently looking for cool apps using Node and Apigee App Services, so if you’re building something interesting, please send us an email to be eligible for Apigee’s $4,000 accelerator prize — you must submit your (finished) app by email between now and midnight Pacific on November 30, 2012. Feel free to contact us beforehand for more details or to tell us about what you’re building!

(protip) Create a Perfect Pitch Video

This year, we’re requiring contestants to submit pitch videos for expert judging (40% of the score).

The point of the pitch video is to make it easier for judges to understand what’s awesome about your entry. It lets you show off your app in the best possible light. For example, if your app goes down or runs into bugs, judges will still be able to give you a decent score.

Below are some tips for creating a perfect pitch video.

Answer 3 Questions

A great pitch video should answer 3 questions about your entry.

1. Who is it for?

What sort of people will use what you’ve built? Are they hackers or painters, consumers or businesses? Are they busy, lazy, bored?

Describing your intended audience helps the video viewer build empathy for the people who have the problem you’re trying to solve.

2. Why would people use it?

What problem does your audience have? How does your service help them solve the problem in a better way than they do it today.

Starting by describing the problem gets people excited to see your solution.

3. How does it work?

Here’s the fun bit. Show how your product or service solves the problem that you just described.

Remember to show your product in the best possible light, set up your demo so that it avoids bugs and skips any tedious slow bits (e.g. data entry).

How to Do It

While you can use any software and service to create and host your video, Google Hangouts is free and very easy to use.

The video at the top of this post how to use Google Hangouts to create a pitch video (woah, recursion).

This is the 17th in a series of posts leading up to Node.js Knockout on getting started with Geddy This post was written by Geddy contributor and Node Knockout Judge Daniel Erickson. It is cross-posted on the Geddy wiki.

Intro

I’ve had a few people ask me to write a quick guide to getting started with authentication and realtime events with Geddy. These are both really amazing new features so I thought I’d oblidge.

Installing Geddy

Installing Geddy is as easy as installing any other global node module:

$ npm install -g geddy

This will get you the latest version of Geddy and all of it’s (minimal) dependencies.

Starting a new project

Likewise, starting a new project is pretty easy too:

$ geddy app -rt node_ko

You’ll notice that -rt option in there - that tells the app generator to include the socket.io integration code in your newly generated app.

Adding user authentication:

Setting up local, Facebook, and Twitter authentication for your users is also very simple, just cd into your project and type:

$ geddy auth

This will generate a User model for us, and it will set up all the routes and views that your users will need to log in. In order for the generated code to work, your app will have to know your client application keys for each of the supported authentication apis.

You’ll need to add the settings for Passport in your app’s environment.js file. That includes the redirect locations for after an auth failure or success, and the OAuth keys for your app. The setting will look something like this:

passport: {
  successRedirect: '/'
, failureRedirect: '/login'
, twitter: {
    consumerKey: 'XXXXXXX'
  , consumerSecret: 'XXXXXXX'
  }
, facebook: {
    clientID: 'XXXXXXX'
  , clientSecret: 'XXXXXXX'
  }
}

Adding some scaffolding

Next we’ll want to scaffold out a resource for us to use. Lets go ahead and create a messages resource:

$ geddy scaffold -rt message body

This will generate a Message model, a messages controller, some message views, and all of the routes needed to perform the basic CRUD actions. Because we used the -rt option, it will also make our models available on the front end and create a socket.io channel so that we can listen for model related lifecycle events on the front end.

Running the app

If you’re running your app locally, all you’ll need to do is run it with the geddy command:

$ geddy

If you’re running your app on a platform that does not allow you to use global modules, you’ll need to create a server.js file in your app’s root directory with these contents:

//web: node node_modules/geddy/bin/cli.js
var geddy = require('geddy');

geddy.start({
  environment: 'production'
});

Customizing the app

First, lets make sure that messages endpoints are secure, we only want logged in users to be able to view, edit, and remove messages.

Open up your app/controllers/messages.js file and add this:

this.before(require(‘../helpers/passport’).requireAuth);

This will require that there is a logged in user before performing an action in the messages controller.

Next, lets make sure that our users are redirected to the right place after they log in. Open up your environment.js file and change passport.successRedirect to /messages. This will redirect users to the messages index route after they successfully log in.

Test out your app

Open up http://localhost:4000/ and check out your app. Log in with one of the links on the home page, check out the realtime stuff by opening two browser windows, signing into both of them, and adding a message in one.

Things you can try to learn more

  • create a new message via ajax so it feels more like a chat room
  • display the date of the message instead of the id
  • make the views a bit prettier

Want to know more?

  • Check out the documentation at http://geddyjs.org/documentation
  • Ask your questions on the mailing list
  • Hop on IRC and get help if you need it: #geddy on freenode

MongoLab provides MongoDB-as-a-Service on the Joyent Cloud (and on Cloud providers) for the lowest latency between your Nodejitsu app and MongoDB. 500MB databases are available for free. In a recent test, ping latency averaged under 800 microseconds between our MongoLab Joyent servers and a hosted jit.su server. We have a web GUI for managing, searching, and editing documents in MongoDB. We also provide an authenticated REST API if you need that.

tl;dr

  1. Visit http://mongolab.com and sign in / create a free account
  2. Click Create new in the Databases section
  3. Select JoyentCloud as the provider, with the Free plan (500 MB), us-east-1 datacenter
  4. Populate the database name and at the bottom, the username and password fields, then click Create database
  5. In the database list, click on the new database to get to the detail page
  6. Connection string is at the top of the page and should look like ds??????.mongolab.com:??????/databasename. Username and password are as you entered them.
  7. Connect and enjoy. Contact support@mongolab.com with any questions

Create a database

  1. Visit http://mongolab.com and create an account or sign in if you have one already.
  2. Click Create new in the Databases section. Alternatively, you can clone an existing database if it’s accessible on the Internet and you have a username and password for it.

Create

Select JoyentCloud, us-east-1

  1. Select JoyentCloud as the provider, with the Free plan (0.5 GB), us-east-1 datacenter.
  2. Populate the database name and at the bottom, the username and password fields, then click Create database.

Database Form

Get your connection string

  1. In the database list, click on the new database to get to the detail page.
  2. Connection string is at the top of the page and should look like ds??????.mongolab.com:??????/databasename. Username and password are as you entered them.
  3. Connect and enjoy. Contact support@mongolab.com with any questions.

Thanks for using our service.

After your database is populated with at least one collection, you can run and save queries, and edit documents directly in our UI. That makes development with MongoDB even easier.

Database Detail

More MongoDB nodeknockout tutorials

A great post by MongoHQ announcing their sponsorship (including $20K in prizes), and also highlighting some of the most exciting things about Node Knockout.

This is the 16th in a series of posts leading up to Node.js Knockout on using jitsu to deploy to Nodejitsu This post was written by Nodejitsu Support Engineer Colton Baker (aka Sly).

TL;DR

$ git clone git@github.com:nko3/[slug].git myapp
$ cd myapp
$ [sudo] npm install -g jitsu
$ jitsu login # username and password provided on your NKO team page
$ jitsu deploy

Installing

To install Jitsu, all you have to do is run: npm install -g jitsu

Hint: If npm throws an error, try using sudo npm install -g jitsu.

Setting up Jitsu

Once you install Jitsu, you will need to login with the password that was provided to your team by NKO. This login, and only this login, will need to be used for each team member. NKO will not accept submissions that are under another Nodejitsu account.

To login, use: jitsu login

Hint: If you get an error when logging in, try using one of the following:

  • jitsu conf set protocol http
  • jitsu conf set host api.nodejitsu.com

Deploying

Before developing your app, you should clone the repository provided to your team by NKO. This will follow the pattern of nko3/[slug]. For example, if your team is named “Node Bandits”, your repository would be nko3/node-bandits.

If you do not have access to this repository, let someone know immediately. This repository provides a skeleton of what NKO is expecting you to submit when you deploy your application.

Once you have this repository checked out, you can code your application however you see fit. Once you’re done, deploy your application to our cloud by running jitsu deploy in the directory containing the package.json file that was provided by your nko3/[slug] repository.

Warning: Make sure you keep version numbers synced across team members. If a team member trying to deploy an application with version 0.0.1 while another team member has deployed 0.0.2, the server will reject the deploy.

Remember:

  • nko3/[slug] should be nko3/your-team-name. For example, a team named “Node Bandits” would be nko3/node-bandits.
  • You get one login for Nodejitsu per team. Use it, because your submissions won’t be accepted from another account.
  • Keep version numbers synced amongst your team. Using different versions could, and probably will, cause unintended effects.

Going deeper

Jitsu has a lot of features including deploying old snapshots, getting running logs, setting environment variables, and even creating databases. More info can be found by just typing jitsu at the command line or in the Nodejitsu Handbook.

Help

You can visit us online at our homepage. You can find out more information about Jitsu on Github. As always, you can also find us on IRC on Freenode on #nodejitsu.

This is the 15th in a series of posts leading up to Node.js Knockout on using mongodb with node-mongodb-native This post was written by Node Knockout judge and node-mongo-db-native author Christian Kvalheim.

MongoDB has native support for geospatial indexes and extensions to the query language to support a lot of different ways of querying your geo spatial documents. We will touch on a all of the available features of the MongoDB geospatial support point by point as outlined below.

  • Query $near a point with a maximum distance around that point
  • Set the minimum and maximum range for the 2d space letting you map any data to the space
  • GeoNear command lets you return the distance from each point found
  • $within query lets you set a shape for you query letting you use a circle, box or arbitrary polygon, letting you map complex geo queries such as congressional districts or post code zones.

But first let’s cover the basics of getting you up and running starting with what a document needs to look like for the indexing to work.

Geospatialize your documents

Somehow we need to tell MongoDB what fields represent our geospatial coordinates. Luckily for us this is very simple. Lets take a simple sample document representing the best imaginative Burger place in the world.

var document = {
  name: "Awesome burger bar"      
}

Not we need know that it’s located on the fictitious planet (Burgoria) and more specifically at the coordinates [50, 50]. So how do we add this to the document so we can look it up using geospatial searches ? Well it’s very simple just add it as a field as shown below.

var document = {
  name: "Awesome burger bar",
  loc: [50, 50]      
}

Easy right? The only thing you have to ensure is that the first coordinate is the x coordinate and the second one is the y coordinate [x, y].

Let’s go ahead and connect to the database and insert the document

var Db = require('mongodb').Db;

var document = {
  name: "Awesome burger bar",
  loc: [50, 50]      
}

Db.connect("mongodb://localhost:27017/geodb", function(err, db) {
  if(err) return console.dir(err)

  db.collection('places').insert(document, {w:1}, function(err, result) {
    if(err) return console.dir(err)
  });
});

So now we have a document in our collection. We now need to tell MongoDB to index our collection and create a 2D index on our loc attribute so we can avail us of the awesome geospatial features. This turns out to be easy as well. Let’s modify the code to ensure we have the index on startup.

var Db = require('mongodb').Db;

var document = {
  name: "Awesome burger bar",
  loc: [50, 50]      
}

Db.connect("mongodb://localhost:27017/geodb", function(err, db) {
  if(err) return console.dir(err)
  var collection = db.collection('places');

  collection.ensureIndex({loc: "2d"}, {min: -500, max: 500, w:1}, function(err, result) {
    if(err) return console.dir(err);

    collection.insert(document, {w:1}, function(err, result) {
      if(err) return console.dir(err)
    });
  });
});

ensureIndex does the trick creating the index if it does not already exist. By specifying {loc: “2d”} MongoDB will index the array contained in every document under the field name loc. The min and max defines the boundaries of our (Burgoria) and means that points outside -500 and 500 will throw an error as it’s not on the planet.

Basic queries for your geospatial documents

Since we now have a geospatial index on our collection let’s play around with the query methods and learn how we can work with the data. First however let’s add some more documents so we can see the effects of the different boundaries.

var Db = require('mongodb').Db;

var documents = [
    {name: "Awesome burger bar", loc: [50, 50]}
  , {name: "Not an Awesome burger bar", loc: [10, 10]}
  , {name: "More or less an Awesome burger bar", loc: [45, 45]}
]

Db.connect("mongodb://localhost:27017/geodb", function(err, db) {
  if(err) return console.dir(err)
  var collection = db.collection('places');

  collection.ensureIndex({loc: "2d"}, {min: -500, max: 500, w:1}, function(err, result) {
    if(err) return console.dir(err);

    collection.insert(documents, {w:1}, function(err, result) {
      if(err) return console.dir(err)
    });
  });
});

Right from now one for brevities sake we are going to assume we have the documents stored in the collection and the index created so we can work on queries without the boilerplate insert and index creation code. The first thing we are going to do is locate all the documents that’s a distance of 10 away from 50, 50.

var Db = require('mongodb').Db,
  assert = require('assert');

Db.connect("mongodb://localhost:27017/geodb", function(err, db) {
  if(err) return console.dir(err)

  db.collection('places').find({loc: {$near: [50,50], $maxDistance: 10}}).toArray(function(err, docs) {
    if(err) return console.dir(err)

    assert.equal(docs.length, 2);
  });
});

This returns the following results (ignore the _id it will be different as it’s a collection assigned key).

{ "_id" : 509a47337d6ab61b2871ee8e, "name" : "Awesome burger bar", "loc" : [ 50, 50 ] }
{ "_id" : 509a47337d6ab61b2871ee90, "name" : "More or less an Awesome burger bar", "loc" : [ 45

Let’s look at the query. $near specifies the center point for the geospatial query and $maxDistance the radius of the search circle. Given this the query will return the two documents at [50, 50] and [10, 10]. Now this is a nice feature but what if we need to know the distance from each of the found documents to the originating center for our query. Luckily we have a command that support that called geoNear. Let’s execute it and look at the results.

var Db = require('mongodb').Db,
  assert = require('assert');

Db.connect("mongodb://localhost:27017/geodb", function(err, db) {
  if(err) return console.dir(err)

  db.collection('places').geoNear(50, 50, {$maxDistance:10}, function(err, result) {
    if(err) return console.dir(err)

    assert.equal(result.results, 2);
  });
});

Let’s look at the results returned by the query.

{ “ns” : “test.places”, “near” : “1100000011110000111100001111000011110000111100001111”, “results” : [ { “dis” : 0, “obj” : { “_id” : 509a47337d6ab61b2871ee8e, “name” : “Awesome burger bar”, “loc” : [ 50, 50 ] } }, { “dis” : 7.0710678118654755, “obj” : { “_id” : 509a47337d6ab61b2871ee90, “name” : “More or less an Awesome burger bar”, “loc” : [ 45, 45 ] } } ], “stats” : { “time” : 0, “btreelocs” : 0, “nscanned” : 2, “objectsLoaded” : 2, “avgDistance” : 3.5355339059327378, “maxDistance” : 7.071128503792992 }, “ok” : 1 }

Notice that geoNear is a command not a find query so it returns a single document with the results in the results field of the returned document. As we can see from the results each returned result has a field called dis that is the distance of the document from the center point of our search. Cool we’ve now covered the basics of geospatial search so let’s move onto more advanced queries.

Advanced queries for your geospatial documents

So besides these simple queries we can also do bounds queries. With bounds queries we mean we can look for points of interest inside a defined boundary. This can be useful if you have such things as a post code area, congressional district or any sort of bounding box that is not a pure circle (say look for all restaurants in the west village in new york). Let’s go through the basics.

The magical boundry box query

Our country Whopper on Burgoria is a perfectly bound box (imagine that). Our application wants to restrict our searches to only burger bars in Burgonia. The boundaries for Burgonia are defined by (30, 30) -> (30, 60) and (30, 60) -> (60, 60). Great let’s peform a box bounded query.

var Db = require('mongodb').Db,
  assert = require('assert');

Db.connect("mongodb://localhost:27017/geodb", function(err, db) {
  if(err) return console.dir(err)
  var box = [[30, 30], [60, 60]];

  db.collection('places').find({loc: {$within: {$box: box}}).toArray(function(err, docs) {
    if(err) return console.dir(err)

    assert.equal(docs.length, 2);
  });
});

The results returned are.

{ "_id" : 509a47337d6ab61b2871ee8e, "name" : "Awesome burger bar", "loc" : [ 50, 50 ] }
{ "_id" : 509a47337d6ab61b2871ee90, "name" : "More or less an Awesome burger bar", "loc" : [ 45

A polygon to far

Awesome we can now do a query by our perfectly boxed country. Inside Whopper the country is split into triangles where triangle one is made up of three points (40, 40), (40, 50), (45, 45). We want to look for points that are only inside this triangle. Let’s have a look at the query.

var Db = require('mongodb').Db,
  assert = require('assert');

Db.connect("mongodb://localhost:27017/geodb", function(err, db) {
  if(err) return console.dir(err)
  var triangle = [[40, 40], [40, 50], [45, 45]];

  db.collection('places').find({loc: {$within: {$polygon: triangle}}).toArray(function(err, docs) {
    if(err) return console.dir(err)

    assert.equal(docs.length, 2);
  });
});

The results returned are.

{ "_id" : ObjectId("509a47337d6ab61b2871ee90"), "name" : "More or less an Awesome burger bar", "loc" : [ 45, 45 ] }

Cool things you can use this with is f.ex with the data at https://nycopendata.socrata.com/browse?tags=geographic you can create queries slicing new york into areas and look for data points inside those areas. So we’ve seen how we can query geo spatially in a lot of different ways. In closing we want to mention some simple ideas to get your mind churning.

Geospatial interesting tidbits

So geospatial is what we mostly promote the features as but at some point you’ll realize that it’s a generic set of 2d indexes that can be used to index and x,y data. You could consider indexing any data points that fit into a 2d space and using the geo query functionality to retrieve subsets of that data. Say if you map price vs apartment size and want to say giving an apartment find me everything that is “close” to the ideal price and size that I’m looking for. The limit here is your fantasy but as you can see it’s a pretty general and very powerful feature once you get over looking at the feature as a pure geographical function. With that I leave you to experiment and have fun with the features we have introduced.

Links and stuff