Conceptos básicos. Seminario web 2: Su primera aplicación MongoDB

Preview:

Citation preview

Back to Basics 2016: Webinar 2Su primera aplicación MongoDB

Rubén TerceñoSenior Solutions Architect, EMEAruben@mongodb.com@rubenTerceno

¡Bienvenidos!

Agenda del CursoDate Time Webinar25-Mayo-2016 16:00 CEST Introducción a NoSQL 7-Junio-2016 16:00 CEST Su primera aplicación MongoDB 21-Junio-2016 16:00 CEST Diseño de esquema orientado a documentos 07-Julio-2016 16:00 CEST Indexación avanzada, índices de texto y geoespaciales 19-Julio-2016 16:00 CEST Introducción al Aggregation Framework 28-Julio-2016 16:00 CEST Despliegue en producción

Resumen del webinar 1• ¿Porqué existe NoSQL?• Tipos de bases de datos NoSQL• Características clave de MongoDB• Tolerancia a fallos y persistencia de datos en MongoDB• Escalabilidad en MongoDB

Agenda• Vocabulario básico• Instalación de MongoDB• Construcción de una aplicación básica• Creación de índices• Optimización de queries con explain()

ConceptsRelational MongoDBDatabase Database / Base de datosTable Collection / ColecciónRow Document / DocumentoIndex Index / ÍndiceJoin LookupForeign Key Reference / ReferenciaMulti-table transaction Single document transaction

Installing MongoDB$ curl -O https://fastdl.mongodb.org/osx/mongodb-osx-x86_64-3.2.6.tgz

$ tar xzvf mongodb-osx-x86_64-3.2.6.tgz x mongodb-osx-x86_64-3.2.6/READMEx mongodb-osx-x86_64-3.2.6/THIRD-PARTY-NOTICESx mongodb-osx-x86_64-3.2.6/MPL-2x mongodb-osx-x86_64-3.2.6/GNU-AGPL-3.0x mongodb-osx-x86_64-3.2.6/bin/mongodumpx mongodb-osx-x86_64-3.2.6/bin/mongorestorex mongodb-osx-x86_64-3.2.6/bin/mongoexportx mongodb-osx-x86_64-3.2.6/bin/mongoimportx mongodb-osx-x86_64-3.2.6/bin/mongostatx mongodb-osx-x86_64-3.2.6/bin/mongotopx mongodb-osx-x86_64-3.2.6/bin/bsondumpx mongodb-osx-x86_64-3.2.6/bin/mongofilesx mongodb-osx-x86_64-3.2.6/bin/mongooplogx mongodb-osx-x86_64-3.2.6/bin/mongoperfx mongodb-osx-x86_64-3.2.6/bin/mongosniffx mongodb-osx-x86_64-3.2.6/bin/mongodx mongodb-osx-x86_64-3.2.6/bin/mongosx mongodb-osx-x86_64-3.2.6/bin/mongo

$ mkdir /data/CB

Running MongodRubens-MacBook-Pro:mongodb-osx-x86_64-3.2.6 Ruben$ ./bin/mongod -dbpath /data/CB

2016-06-05T14:44:49.564+0200 I CONTROL [initandlisten] MongoDB starting : pid=21526 port=27017 dbpath=/data/CB 64-bit host=Rubens-MacBook-Pro.local2016-06-05T14:44:49.564+0200 I CONTROL [initandlisten] db version v3.2.62016-06-05T14:44:49.564+0200 I CONTROL [initandlisten] git version: 05552b562c7a0b3143a729aaa0838e558dc49b252016-06-05T14:44:49.564+0200 I CONTROL [initandlisten] allocator: system2016-06-05T14:44:49.564+0200 I CONTROL [initandlisten] modules: none2016-06-05T14:44:49.564+0200 I CONTROL [initandlisten] build environment:2016-06-05T14:44:49.564+0200 I CONTROL [initandlisten] distarch: x86_642016-06-05T14:44:49.564+0200 I CONTROL [initandlisten] target_arch: x86_642016-06-05T14:44:49.564+0200 I CONTROL [initandlisten] options: { storage: { dbPath: "/data/CB" } }2016-06-05T14:44:49.565+0200 I STORAGE [initandlisten] wiredtiger_open config: create,cache_size=9G,session_max=20000,eviction=(threads_max=4),config_base=false,statistics=(fast),log=(enabled=true,archive=true,path=journal,compressor=snappy),file_manager=(close_idle_time=100000),checkpoint=(wait=60,log_size=2GB),statistics_log=(wait=0),2016-06-05T14:44:50.316+0200 I NETWORK [HostnameCanonicalizationWorker] Starting hostname canonicalization worker2016-06-05T14:44:50.316+0200 I FTDC [initandlisten] Initializing full-time diagnostic data capture with directory '/data/CB/diagnostic.data'2016-06-05T14:44:50.511+0200 I NETWORK [initandlisten] waiting for connections on port 27017

Connecting Via The ShellRuben$ ./mongodb-osx-x86_64-3.2.6/bin/mongoMongoDB shell version: 3.2.6connecting to: test> show databaseslocal 0.000GB

Inserting your first record> use CBswitched to db CB> show databaseslocal 0.000GB> db.demo.insert({"nombre": "Rubén", "altura": 178})WriteResult({ "nInserted" : 1 })> show databasesCB 0.000GBlocal 0.000GB> show collectionsdemo> db.demo.findOne(){

"_id" : ObjectId("575420c87a75dbb02b4f45cb"),"nombre" : "Rubén","altura" : 178

}>

Object ID

575420c87a75dbb02b4f45cbTS------ID----PID-Count-

A Simple Blog Application• Lets create a blogging application with:

• Articles• Users• Comments

15

Typical Entity Relation Diagram

In MongoDB we build organically> use blogswitched to db blog> db.users.insert( { "username" : ”rterceno", "password" : "top secret", "lang" : "ES" } )WriteResult({ "nInserted" : 1 })> db.users.findOne(){

"_id" : ObjectId("573afff65ee4be80385332a7"),"username" : "rterceno","password" : "top secret","lang" : "ES"

}

How do we do this in a program?package com.mongodb.rterceno;

import com.mongodb.MongoClient;import com.mongodb.client.MongoCollection;import com.mongodb.client.MongoDatabase;import org.bson.Document;

public class Demo { public static void main(String[] args) { MongoClient client = new MongoClient(); MongoDatabase blog = client.getDatabase("blog"); MongoCollection<Document> users = blog.getCollection("users"); Document user = new Document("user","rterceno") .append("lang", "ES");

users.insertOne(user); }}

Next up Articlesimport [+]import static java.util.Arrays.asList;

public class Demo {

public static void main(String[] args) {

MongoClient client = new MongoClient(); MongoDatabase blog = client.getDatabase("blog"); MongoCollection<Document> articulos = blog.getCollection("articles");

String myName = "rterceno";

Document articulo = new Document("título","My article") .append("autor", myName) .append("texto", "Lorem ipsum dolor sit amet, […] commodo consequat.") .append("tags", asList("demo","español","MongoDB"));

articulos.insertOne(articulo); } }

Create a new type of articlepublic class Demo {

static DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'" , Locale.ENGLISH);

public static void main(String[] args) {

MongoClient client = new MongoClient(); MongoDatabase blog = client.getDatabase("blog"); MongoCollection<Document> articulos = blog.getCollection("articles"); String myName = "rterceno";

Document articulo = new Document("título","My article") .append("autor", myName) .append("texto", "Lorem ipsum dolor sit amet […] commodo consequat.") .append("tags", asList("demo", "español", "MongoDB")) .append("fecha", new Date()); articulos.insertOne(articulo); }}

Make a lot of articles public class Demo {

static DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'" , Locale.ENGLISH); public static void main(String[] args) {

MongoClient client = new MongoClient(); MongoDatabase blog = client.getDatabase("blog"); MongoCollection<Document> articulos = blog.getCollection("articles");

List<Document> list = new ArrayList<Document>();

for (int i=0; i<1000000; i++){ Document articulo = new Document("título”, "Mi artículo " + i) .append("autor", "USER_" + Math.round(Math.random()*10000)) .append("texto", "Lorem ipsum dolor sit amet, […] ex ea commodo consequat.") .append("tags", asList("demo", "español", "MongoDB")) .append("fecha", new Date());

list.add(articulo);

if (i % 5000 == 4999){ articulos.insertMany(list); list.clear(); } } }}

Find a User> db.users.findOne(){

"_id" : ObjectId("5742da5bb26a88bc00e941ac"),"username" : "FLFZQLSRWZ_0","lang" : "EN","password" : "vTlILbGWLt","karma" : 448

}> db.users.find( { "username" : "VHXDAUUFJW_45" } ).pretty(){

"_id" : ObjectId("5742da5bb26a88bc00e94206"),"username" : "VHXDAUUFJW_45","lang" : "EN","password" : "GmRLnCeKVp","karma" : 284

}

Find Users with high Karma> db.users.find( { "karma" : { $gte : 450 }} ).pretty(){

"_id" : ObjectId("5742da5bb26a88bc00e941ae"),"username" : "JALLFRKBWD_1","lang" : "EN","password" : "bCSKSKvUeb","karma" : 487

}{

"_id" : ObjectId("5742da5bb26a88bc00e941e4"),"username" : "OTKWJJBNBU_28","lang" : "EN","password" : "HAWpiATCBN","karma" : 473

}{

Using projection > db.users.find( { "karma" : { $gte : 450 }}, { "_id" : 0, username : 1, karma : 1 } ){ "username" : "JALLFRKBWD_1", "karma" : 487 }{ "username" : "OTKWJJBNBU_28", "karma" : 473 }{ "username" : "RVVHLKTWHU_31", "karma" : 493 }{ "username" : "JBNESEOOEP_48", "karma" : 464 }{ "username" : "VSTBDZLKQQ_51", "karma" : 487 }{ "username" : "UKYDTQJCLO_61", "karma" : 493 }{ "username" : "HZFZZMZHYB_106", "karma" : 493 }{ "username" : "AAYLPJJNHO_113", "karma" : 455 }{ "username" : "CXZZMHLBXE_128", "karma" : 460 }{ "username" : "KKJXBACBVN_134", "karma" : 460 }{ "username" : "PTNTIBGAJV_165", "karma" : 461 }{ "username" : "PVLCQJIGDY_169", "karma" : 463 }

Using sort> db.users.find({"karma”: {$gte: 450}},{"_id”: 0, username: 1, karma: 1}).sort({"karma”: 1}){ "username" : "JALLFRKBWD_1", "karma" : 493 }{ "username" : "OTKWJJBNBU_28", "karma" : 493 }{ "username" : "RVVHLKTWHU_31", "karma" : 487 }{ "username" : "JBNESEOOEP_48", "karma" : 474}{ "username" : "VSTBDZLKQQ_51", "karma" : 473 }{ "username" : "UKYDTQJCLO_61", "karma" : 468 }{ "username" : "HZFZZMZHYB_106", "karma" : 464 }{ "username" : "AAYLPJJNHO_113", "karma" : 461 }{ "username" : "CXZZMHLBXE_128", "karma" : 461 }{ "username" : "KKJXBACBVN_134", "karma" : 460 }{ "username" : "PTNTIBGAJV_165", "karma" : 458 }{ "username" : "PVLCQJIGDY_169", "karma" : 455 }

Article update: adding comments 1> db.articles.find( { "_id" : 19 } ).pretty(){

"_id" : 19,"body" :

"nTzOofOcnHKkJxpjKAyqTTnKZMFzzkWFeXtBRuEKsctuGBgWIrEBrYdvFIVHJWaXLUTVUXblOZZgUqWu",

"postdate" : ISODate("2016-05-23T12:02:46.830Z"),"author" : "ASWTOMMABN_19","title" : "CPMaqHtAdRwLXhlUvsej"

} > db.articles.update( { _id : 18 }, { $set : { comments : [] }} )WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

Article update: adding comments 2> db.articles.find( { _id :18 } ).pretty(){

"_id" : 18,"body" :

"KmwFSIMQGcIsRNTDBFPuclwcVJkoMcrIPwTiSZDYyatoKzeQiKvJkiVSrndXqrALVIYZxGpaMjucgXUV",

"postdate" : ISODate("2016-05-23T16:04:39.497Z"),"author" : "USER_18","title" : "wTLreIEyPfovEkBhJZZe","comments" : [ ]

}>

Article update: adding comments 3> db.articles.update( { _id : 18 }, { $push : { comments : { username : ”USER_123456", comment : "Primer!" }}} )WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

> db.articles.find( { _id :18 } ).pretty(){

"_id" : 18,"body" : "KmwFSIMQGcIsRNTDBFPuclJkoMcrIPwTiSZDYyatoKzeQiKvJkiVSrndXqrALVIYZxGpaMjucgXUV","postdate" : ISODate("2016-05-23T16:04:39.497Z"),"author" : "USER_18","title" : "wTLreIEyPfovEkBhJZZe","comments" : [

{"username" : "USER_123456","comment" : ”Primer!"

}]

}

Article delete> db.articles.remove( { "_id" : 25 } )WriteResult({ "nRemoved" : 1 })> db.articles.remove( { "_id" : 25 } )WriteResult({ "nRemoved" : 0 })> db.articles.remove( { "_id" : { $lte : 5 }} )WriteResult({ "nRemoved" : 6 })

• Deletion leaves holes• Dropping a collection is cheaper than deleting a large collection element by

element

Remember Users and Articles> db.users.findOne(){

"_id" : ObjectId("57431c07b26a88bf060e10cb"),"username" : "USER_0","lang" : "EN","password" : "kGIxPxqKGJ","karma" : 266

}> db.articles.findOne(){

"_id" : 0,"body" :

"hvJLnrrfZQurmtjPfUWbMhaQLZjsxHXbUycmJVZTeOZesTnZtojThrebRcUoiYwivjpwG","postdate" : ISODate("2016-05-23T16:04:39.246Z"),"author" : "USER_0","title" : "gpNIoPxpfTAxWjzAVoTJ"

}

Find a User> db.users.find( { "username" : "USER_123456" } ).explain(){

"queryPlanner" : {"plannerVersion" : 1,"namespace" : "blog.users","indexFilterSet" : false,"parsedQuery" : {"username" : {"$eq" : ”USER_123456"}},"winningPlan" : {"stage" : "COLLSCAN","filter" : {"username" : {"$eq" : ”USER_123456"}},"direction" : "forward"},"rejectedPlans" : [ ]} "ok" : 1

}

Find a User – Execution Stats> db.users.find( {"username" : "USER_999999" } ).explain( "executionStats" ).executionStats{

"executionSuccess" : true,"nReturned" : 1,"executionTimeMillis" : 433,"totalKeysExamined" : 0,"totalDocsExamined" : 1000000,"executionStages" : {"stage" : "COLLSCAN","filter" : {"username" : {"$eq" : "USER_999999”}},"nReturned" : 1,"executionTimeMillisEstimate" : 330,"works" : 1000002,"advanced" : 1,"needTime" : 1000000,"needYield" : 0,"saveState" : 7812,"restoreState" : 7812,"isEOF" : 1,"invalidates" : 0,"direction" : "forward","docsExamined" : 1000000

We need an index> db.users.createIndex( { username : 1 } ){

"createdCollectionAutomatically" : false,"numIndexesBefore" : 1,"numIndexesAfter" : 2,"ok" : 1

}

Indexes Overview• Parameters

• Background : Create an index in the background as opposed to locking the database

• Unique : All keys in the collection must be unique. Duplicate key insertions will be rejected with an error.

• Name : explicitly name an index. Otherwise the index name is selfgenerated from the index fields.

• Deleting an Index• db.users.dropIndex({ “username” : 1 })

• Get All the Indexes on a collection• db.users.getIndexes()

Query Plan Execution Stages• COLLSCAN : for a collection scan• IXSCAN : for scanning index keys• FETCH : for retrieving documents• SHARD_MERGE : for merging results from shards

Add an Index> db.users.find( {"username" : "USER_999999”} ).explain("executionStats”).executionStats{

"executionSuccess" : true,"nReturned" : 1,"executionTimeMillis" : 0,"totalKeysExamined" : 1,"totalDocsExamined" : 1,

Execution Stage"executionStages" : {

"stage" : "FETCH","nReturned" : 1,"executionTimeMillisEstimate" : 0,"docsExamined" : 1,,"inputStage" : {

"stage" : "IXSCAN","nReturned" : 1,"executionTimeMillisEstimate" : 0,"keyPattern" : {

"username" : 1},"indexName" : "username_1","indexVersion" : 1,"direction" : "forward","indexBounds" : {

"username" : ["[\"USER_999999\", \"USER_999999\"]”]},

"keysExamined" : 1,"seenInvalidated" : 0 } } }

Drivers and Frameworks

¿Qué hemos aprendido?• Cómo crear una base de datos y una colección• Como insertar documentos• Cómo realizar búsquedas• Como hacer modificaciones de los documentos existentes• Cómo borrar documentos• Cómo comprobar la eficiencia de una operación• Cómo crear índices• Cómo averiguar los índices que se utilizan en una operación

Próximo WebinarDiseño de esquema orientado a documentos

• 21 de Junio 2016 – 16:00 CEST, 11:00 ART, 9:00

• ¡Regístrese si aún no lo ha hecho!

• Las bases de datos de documentos requieren un enfoque distinto con respecto a la organización de los datos.

• ¡Sin normalización! Creamos esquemas adaptados a nuestra aplicación • Optimizaremos dichos esquemas a los patrones de acceso.• Demostraremos que es fácil controlar estos esquemas.

• Regístrese en : https://www.mongodb.com/webinars

• Denos su opinión, por favor: back-to-basics@mongodb.com

¿Preguntas?