MongoDB (from “humongous”) is an open source document-oriented database system developed and supported by 10gen (founded by Dwight Merriman). First publicly released in 2009, and since then it have been a rising star in the NoSQL world. MongoDB stores structured data as JSON-like documents with dynamic schemas (technically data is stored in a binary form of JSON known as BSON), making the integration of data in certain types of applications easier and faster.
To start MongoDB, open the command prompt window, and run mongod.exe
from the bin directory (specify the data path if needed)
The
waiting for connections
message in the console output indicates that
the mongod.exe process is running successfully and waiting for
connections on port 27017
To connect to the server, open another command prompt window and run
mongo.exe from the bin directory.
In case you want to remove MongoDB service C:\mongodb\bin\mongod.exe –remove
Data in MongoDB has a flexible schema.
Based on what we mentioned, you could say that MongoDB is schema-less. But you may refer to this data modeling article before doing real work on MongoDB.
db.towns.insert({
name: “New York”,
population: 22200000,
last_census: ISODate(“2009-07-31”),
famous_for: [ “statue of liberty”, “food” ],
mayor : {
name : “Michael Bloomberg”,
party : “I”
}
})
To show a list of collections, use show collections.
To list the contents of a collection, use db.towns.find()
MongoDB commands are JavaScript functions.
Functions You can create JavaScript functions and call them on the mongo shell like:
function insertCity( name, population, last_census, famous_for, mayor_info) {
db.towns.insert({
name:name,
population:population,
last_census: ISODate(last_census),
famous_for:famous_for,
mayor : mayor_in fo
});
}
insertCity(“Punxsutawney”, 6200, ‘2008-31-01’, [“phil the groundhog”], { name : “Jim Wehrle” } )
insertCity(“Portland”, 582000, ‘2007-20-09’, [“beer”, “food”], { name : “Sam Adams”, party : “D” } )
Now have three towns in our collection
db.towns.find({ “_id” : ObjectId(“51def56c1cf66f4c40bb7f4a”) })
db.towns.find({ “_id” : ObjectId(“51def56c1cf66f4c40bb7f4a”) }, { name : 1})
db.towns.find({ “_id” : ObjectId(“51def56c1cf66f4c40bb7f4a”) }, { name : 0})
db.towns.find( { name : /^P/, population : { $lt : 10000 } }, { name :
1, population : 1 } )
We said before that the query language is JavaScript, which means we can
construct operations as we would construct objects. In the following
query, we build a criteria where the population must be between 10.000
and 1 million. Ranges work also on dates.
> var population_range = {}
> population_range[’$lt’] = 100000
100000
> population_range[’$gt’] = 10000
10000
> population_range[’$lt’] = 1000000
1000000
> population_range[’$gt’] = 10000
10000
> db.towns.find( {name : /^P/, population : population_range },
{name: 1})
{ “_id” : ObjectId(“51df08e72476b99608460870”), “name” : “Portland”
}
> db.towns.find( { famous_for : ‘food’ },
{ _id : 0, name : 1, famous_for : 1 } )
{ “name” : “New York”, “famous_for” : [ “statue of liberty”, “food”
] }
{ “name” : “Portland”, “famous_for” : [ “beer”, “food” ] }
> db.towns.find( { famous_for : /statue/ }, { _id : 0, name : 1,
famous_for : 1 } )
{ “name” : “New York”, “famous_for” : [ “statue of liberty”, “food”
] }
> db.towns.find( { famous_for : { $all : [‘food’, ‘beer’] } }, {
_id : 0, name:1, famous_for:1 } )
{ “name” : “Portland”, “famous_for” : [ “beer”, “food” ] }
> db.towns.find( { famous_for : { $nin : [‘food’, ‘beer’] } }, {
_id : 0, name : 1, famous_for : 1 } )
{ “name” : “Punxsutawney”, “famous_for” : [ “phil the groundhog” ]
}
> db.towns.find( { ‘mayor.party’ : {
$exists : false } }, { _id : 0, name : 1, mayor : 1 } )
{ “name” : “Punxsutawney”, “mayor” : { “name” : “jim Wehrle” }
}
$elemMatch helps us specify if a document or a nested document matches
all of our criteria, the document counts as a match and returned. We can
use any advanced operators within this criteria. To show it in action,
let’s insert some data into a new collection countries
> db.countries.insert({ _id : “us”,
… name : “United States”,
… exports : {
… foods : [
… { name : “bacon”, tasty : true },
… { name : “burgers” }
… ]
… }
… })
> db.countries.insert({ _id : “ca”,
… name : “Canada”,
… exports : {
… foods : [
… { name : “bacon”, tasty : false },
… { name : “syrup”, tasty : true }
… ]
… }
… })
> db.countries.insert({ _id : “mx”,
… name : “Mexico”,
… exports : {
… foods : [
… { name : “salsa”, tasty : true, condiment : true }
… ]
… }
… })
> print( db.countries.count() )
3
Now if we need to select countries that export tasty bacon, we should
$elemMatch in a query like:
> db.countries.find(
… {
… ’exports.foods’ : {
… $elemMatch : {
… name : “bacon”,
… tasty : true
… }
… }
… },
… { _id : 0, name : 1 }
… )
{ “name” : “United States” }
If we didn’t used $elemMatch and wrote a query like the following, it
will return countries that export bacon or tasty food, not tasty bacon
> db.countries.find(
… { ’exports.foods.name’ : ‘bacon’ , ’exports.foods.tasty’ : true },
… { _id : 0, name : 1 }
… )
{ “name” : “United States” }
{ “name” : “Canada” }
$or a prefix for criteria to return document that match either
condition1 or condition2. There is a a lot of
operators
you can use.
> db.countries.find({
… $or : [ { _id : “mx” } , { name : “United States” } ] },
… {_id : 1} )
{ “_id” : “us” }
{ “_id” : “mx” }
Although MongoDB is schema-less but you can make one document reference
another document using a construct like { $ref : “collection_name”,
$id : “reference_id” }. In the following query we linking New York
town with the country US. Notice the display of the new country field in
the New York town document.
> db.towns.update(
… { _id : ObjectId(“51def56c1cf66f4c40bb7f4a”) },
… { $set : { country : { $ref : “countries”, $id : “us” } } }
… )
> db.towns.find( { _id : ObjectId(“51def56c1cf66f4c40bb7f4a”) } )
{ “_id” : ObjectId(“51def56c1cf66f4c40bb7f4a”), “country” : DBRef(“countries”, “us”),
“famous_for” : [ “statue of liberty”, “food” ], “last_census” :
ISODate(“2009-07-31T00:00:00Z”), “mayor” : { “na
me” : “Michael Bloomberg”, “party” : “I” }, “name” : “New York”,
“population” : 22200000 }Now we can
retrieve New york from towns collection, then use it to retrieve its
country
> var NY = db.towns.findOne( { _id :
ObjectId(“51def56c1cf66f4c40bb7f4a”) } )
> db.countries.findOne( { _id : NY.country.$id })
{
“_id” : “us”,
“name” : “United States”,
“exports” : {
“foods” : [
{
“name” : “bacon”,
“tasty” : true
},
{
“name” : “burgers”
}
]
}
}
or in a different way > db[
NY.country.$ref ].findOne( { _id : NY.country.$id} )
Removing documents
from a collections is simple, use your criteria with a call to
remove() function and all matching documents will be removed. It’s a
recommended practice to build your criteria in an object, use that
criteria to ensure that matching documents are the expected ones, pass
this criteria to remove() function.
> var bad_bacon = { ’exports.foods’ : {
… $elemMatch : { name : ‘bacon’, tasty : false }
… } }
> db.countries.find ( bad_bacon)
{ “_id” : “ca”, “name” : “Canada”, “exports” : { “foods” : [
{ “name” : “bacon”, “tasty” : false }, { “name” :
“syrup”, “tasty” : true } ] } }
> db.coun tries.remove( bad_bacon)
> db.countries.count()
2
You could ask MongoDb to run a decision function across documents.
db.towns.find( function() {
return this.population > 6000 && this.population < 600000;
} )
or in a short-hand format db.towns.find(“this.population > 6000 &&
this.population < 600000”)
or combine custom code with other criteria
using $where
db.towns.find( {
$where : “this.population > 6000 && this.population < 600000”,
famous_for : /groundhog/
} )
Custom code should be your last resort due to the following:
In this post we explored the basics of MongoDB, a rising star in the NoSQL family and the most common document database. We saw how to install and configure it. We saw how we can store nested structured data as JSON objects and query that data at any depth. We How we can update and delete data. In the next post we going to dig deep into MongoDB.