📜 ⬆️ ⬇️

MongoDb for developers. Week 1

Good evening, Habr. Last week, started the course "MongoDb for developers" from 10gen, which has already been written on Habré . If you watched the lessons, you can safely pass by. The rest is welcome.

This article will set out the main material of the first week of training. If the audience shows interest, then these posts will be published at the end of each week.

We will briefly look at what MongoDB is, compare the difference in data structures between mongo and relational databases for a simple web application, play around with the shell, and skip the php and python for a bit.
')
Why this article? I foresee a similar question. Not everyone managed to enroll in courses, not everyone has enough free time, not everyone is well with the perception of spoken English. Well, for googling such material does not hurt.


MongoDb is a non-relational database for storing JSON documents. Consider some abstract copy of the Mongo collection
{a:3
b:7
fruit:["apple","banana","peach"]}

We see that this document has integer keys a and b and the key fruit which is an array. In relational databases, this behavior is not possible. It is worth noting that such a presentation of data is much closer to the code than that with which we deal with relational databases.

Collections in MongoDb are not tied to a predefined schema (schemaless). For example, the following documents may be elements of one collection.
{a:1,b2}
{a:2,b:4,c:10}

Remember how many times you had to gnash your teeth to make ALTER TABLE, adding a new field, which far from all elements will use? With MongoDb, this is in the past.

If you look at the crookedly drawn scheme below, you can see that in the world of data storage, there are two opposite poles. Nimble, but poor in storage functionality, key values ​​(such as memcached) and extremely functional relational databases, which have problems with performance and scalability.


One of the fundamental ideas of MongoDb is to provide a wide range of options, while maintaining high performance. Of course you have to sacrifice something. For example, Mongo has no analogue join: it is impossible to combine the elements of two different collections. The second important difference from relational databases is the lack of transactions. The latter sounds scary, but the fact is that in Mongo you will not need transactions, in those situations where they would be necessary when using a relational database.

From words to deeds
To continue, we will need to install MongoDb. You will most likely find a fresh version in the repository of your distribution, in the absence of one, the source code is available on the official website. There are also binaries for win and mac. It is worth noting that the 32-bit version has significant limitations on the amount of stored data, so that it can only be used for development. Now for us it does not matter.
Install, run and go to the shell.

 dirtyhack@dirtyhack-ThinkPad-Edge-E125:~$ mongo MongoDB shell version: 2.0.4 connecting to: test > 


While we do not have any data, mongo has created for us a test base, with which we will work. Put our first element in it

 > db.users.save({name:"Woody",age:23}); > db.users.find().pretty() { "_id" : ObjectId("508ea7f33cc5578ed9ecbf46"), "name" : "Woody", "age" : 23 } > 

There are many interesting things at once. Using the db.users.save () command, we sent a request to save the document to the users collection of the current database. Previously, this collection did not exist, it was automatically created upon request.

 > show collections system.indexes users > 

We saved a simple json document in the users collection, with name and age keys. It is easy to guess about the purpose of the find command - it is worth noting that in the case when we are only interested in one document, use the findOne () command. The pretty () command does not affect the logic; it simply displays the result in an easy-to-read form — without it, we would get a string, which is not convenient when working with complex objects.

It's time to add an element to the collection more difficult, and clearly demonstrate the lack of schema mongo.

 > db.users.save({name:"Bazz",age:23,place_of_birth: {country:"unknown",region:"unknown"},interests:["flying","fighting with evil"]}); > db.users.find({name:"Bazz"}).pretty() { "_id" : ObjectId("508eab333cc5578ed9ecbf47"), "name" : "Bazz", "age" : 23, "place_of_birth" : { "country" : "unknown", "region" : "unknown" }, "interests" : [ "flying", "fighting with evil" ] } > 


The second document we added is already more like real data. Note that the values ​​of the place_of_birth and interests elements are nested dictionary documents (JSONObject) and array (JSONArray), respectively. Hierarchical nesting - limited to common sense and a limit of 16 megabytes per item.

By the way, we can use the built-in javascript interpreter
 > var j=db.users.findOne({name:"Woody"}) > j.age=25 25 > db.users.save(j) > db.users.find({name:"Woody"}).pretty() { "_id" : ObjectId("508ea7f33cc5578ed9ecbf46"), "name" : "Woody", "age" : 25 } > 


You've probably already noticed that each element is assigned an ID _id. We will talk about it a little later, we only note that it is unique within the same collection.

We use the resulting collection in a small application, at the end of the article.

Design
Consider how a simple web application data structure will look like in Mongo and a relational database.

Imagine that we have a blog with basic functionality. Authors can post posts by attaching tags to them, users can search by tags and leave comments on posts.

When using a relational database, we need tables to store data about authors, posts, and comments. Also, we will most likely need additional tables to store links between the tables. Of course, according to your realities, you can denormalize your blog base, but in its basic form, it will look something like this.


In MongoDb for the storage of similar data, two collections will be enough for us. I hope the handwriting of Mr. Erlikson is quite legible in the picture.

If you noticed - in the authors' collection as a unique _id it is proposed to use the login. Yes, the identifier can be set (observing the uniqueness of course), if it is not specified, the system will do it for you.
As you can see, the data structure in Mongo is noticeably simpler, and as I noted above, it is much closer to representing the data in code.
You are probably already tired of my outpourings, so one more remark about the identifiers, and finally.
Setting an identifier is an operation with high priority. It is set before the actual data is saved. By default, the Mongo driver does not wait for a response from the database about storing data, receives an identifier and returns the answer to the user. If this behavior does not suit you, you can use safe mode, but be prepared for some loss of performance.

Write the code, your mother.

In the first week lessons, most of the code was presented by the basic lessons on python and the bottle framework. In the next lesson, we will work with the blog's course project on python and pkhp, but for now we will create a simple application that demonstrates how to work with MongoDb from code.

In view of the elementary nature of the actions, we will not create any abstractions and will do everything in the forehead (colleagues will probably think that I am sick). I think you can perfectly write dao-layers.

We will create a simple web application that displays the names and ages of users from the users collection and allows new items to be added to the collection.

To run the example on python, you need the pymongo driver and the framework framework. To run the example in php, you also need a driver, you can take it from pear (don't forget to add mongo.so to the list of extensions).

So examples
Python
index.py
 import bottle import pymongo import sys #       #     ,      ,       #    connection=pymongo.Connection("mongodb://localhost",safe=True) #       db=connection.test @bottle.route('/') def home_page(): #    users=db.users.find(); return bottle.template('index',{"users":users}) @bottle.post('/submit') def submit_page(): #      user={'name':bottle.request.forms.get("name"),'age':bottle.request.forms.get("age")} # db.users.insert(user) bottle.redirect('/') bottle.debug() bottle.run(host="localhost",port=8080) 


views / index.tpl
 <!DOCTYPE html> <html> <head> <title>Hello world</title> </head> <body> <p>   </p><ul> %for user in users: <li>:{{user['name']}} :{{user['age']}}</li> %end </ul> <form action="/submit" method="POST">   <br> <input type="text" name="name" size=40 value=""><br> <input type="text" name="age" size=40 value=""><br> <input type="submit" value="submit"> </form> </body> </html> 


Php
The example on pkhp differs rare simplicity

 <? $mongo = new Mongo('localhost'); $database = $mongo -> test; if ($_POST) $database -> users -> insert($_POST); $users = $database -> users -> find(); ?> <!DOCTYPE html> <html> <head> <title>Hello world</title> </head> <body> <?var_dump($users)?> <p>   </p><ul> <?foreach($users as $user){?> <li>:<?=$user['name']?> :<?=$user['age']?></li> <?}?> </ul> <form action="/" method="POST">   <br> <input type="text" name="name" size=40 value=""><br> <input type="text" name="age" size=40 value=""><br> <input type="submit" value="submit"> </form> </body> </html> 


An important question to those who are interested in examples on php. In the future, the code will be more complicated, you can use Yii or ZF, or a handwritten microframework - I'm waiting for your wishes.

That's all, I hope not in vain tried. If the article is liked by the observers - next week, I will publish a report on the second week, during which CRUD operations will be considered.

Source: https://habr.com/ru/post/156633/


All Articles