SlideShare ist ein Scribd-Unternehmen logo
1 von 175
Downloaden Sie, um offline zu lesen
MongoDB für
Java-Programmierer
Uwe Seiler
uweseiler
About me

Big Data Nerd

Hadoop Trainer MongoDB Author

Photography Enthusiast

Travelpirate
About us
is a bunch of…

Big Data Nerds

Agile Ninjas

Continuous Delivery Gurus

Join us!
Enterprise Java Specialists Performance Geeks
Agenda
•

Buzzword Bingo

•

Überblick über MongoDB

•

Datenmanipulation

•

Indexing

• Konsistenz beim Schreiben und Lesen

von Daten
• Java API & Frameworks
Buzzword Bingo
NoSQL
Klassifizierung von NoSQL
Key-Value Stores

Column Stores

K

V

K

V

1

K

V

K

V

1
1

K

V

Graph Databases

1

1

1
1
1
1
1

1

Document Stores
_id
_id
_id
Big Data
Meine Lieblingsdefinition
Die klassische Definition
•

The 3 V’s of Big Data

Volume Velocity •Variety
«Big Data» != Hadoop
Horizontale
Skalierung
Vertikale Skalierung

RAM
CPU
Storage
Vertikale Skalierung

RAM
CPU
Storage
Vertikale Skalierung

RAM
CPU
Storage
Horizontale Skalierung

RAM
CPU
Storage
Horizontale Skalierung

RAM
CPU
Storage

RAM
CPU
Storage

RAM
CPU
Storage

RAM
CPU
Storage

RAM
CPU
Storage
Horizontale Skalierung
RAM
CPU
Storage

RAM
CPU
Storage

RAM
CPU
Storage

RAM
CPU
Storage

RAM
CPU
Storage

RAM
CPU
Storage

RAM
CPU
Storage

RAM
CPU
Storage

RAM
CPU
Storage

RAM
CPU
Storage

RAM
CPU
Storage

RAM
CPU
Storage

RAM
CPU
Storage

RAM
CPU
Storage

RAM
CPU
Storage
Das Problem
mit der
Verteilung
Das CAP Theorem
Availability
Jede Anfrage
bekommt eine
Antwort

Consistency
Alle Knoten
haben
jederzeit die
gleichen
Informationen

Partition
Tolerance
Trotz
Knotenausfall
funktioniert
das System
Überblick über NoSQL Systeme

Availability
Jeder Client
kann immer
schreiben und
lesen

C

onsistency

Alle Knoten
haben
jederzeit die
gleichen
Informationen

Partition
Tolerance
Trotz
Knotenausfall
funktioniert
das System
Das Problem
mit der
Konsistenz
ACID

vs.
BASE
ACID vs. BASE

1983

Atomicity RDBMS
Consistency
Isolation
Durability
ACID vs. BASE

ACID ist ein gutes
Konzept, aber es ist
kein in Stein
gemeißeltes Gesetz!
ACID vs. BASE

Basically Available
Soft State
2008

NoSQL

Eventually consistent
ACID vs. BASE
ACID

BASE

-

-

Starke Konsistenz
Isolation
Zwei-Phasen-Commit
Komplexe Entwicklung
Zuverlässiger

Schwache Konsistenz
Verfügbarkeit
"Fire-and-forget"
Leichtere Entwicklung
Schneller
Überblick über MongoDB
MongoDB ist eine …
•

Dokumenten-basierte

•

Open Source

•

Performante

•

Flexible

•

Skalierbare

•

Hochverfügbare

•

Funktionsreiche

…Datenbank
Dokumenten-basierte Datenbank
•

Nicht im Sinne einer Datenbank für PDFoder Worddokumente…
Open Source Datenbank
•

MongoDB ist ein Open Source Projekt

•

Auf GitHub
– https://github.com/mongodb/mongo

•

Steht unter der AGPL Lizenz

•

Gestartet und gesponsert von MongoDB
Inc. (früher: 10gen)

•

Kommerzielle Lizenzen sind verfügbar

•

Jeder darf mitmachen!
– https://jira.mongodb.org
Performance

Datenlokalität

In-Memory
Caching

In-Place
Updates
Flexibles Schema
MongoDB

RDBMS
{

_id :
ObjectId("4c4ba5e5e8aabf3"),
employee_name: "Dunham, Justin",
department : "Marketing",
title : "Product Manager, Web",
report_up: "Neray, Graham",
pay_band: “C",
benefits : [
{ type : "Health",
plan : "PPO Plus" },
{ type :
"Dental",
plan : "Standard" }
]
}
Skalierbarkeit
Auto-Sharding

• Erhöhung der Kapazität wenn nötig
• Ausgelegt für Commodity Hardware
• Funktioniert mit Cloud-Architekturen
Hochverfügbarkeit

• Automatische Replikation und Failover
• Unterstützung für mehrere Datenzentren
• Ausgelegt auf möglichst einfachen Betrieb
• Beständigkeit und Konsistenz der Daten
MongoDB Architektur
Reichhaltige Abfragen
Aggregation Framework
Map/Reduce
MongoDB

Data

Map()
emit(k,v)

Group(k)

Shard 1
Sort(k)
Shard 2

…
Shard
n

Reduce(k, values)

Finalize(k, v)
Geoinformationen
Treiber & Shell
Treiber verfügbar für
die populärsten
Programmiersprachen
und Frameworks

Java

JavaScript

Python

Shell zur Interaktion mit
der Datenbank

Ruby

Perl

Haskell

> db.collection.insert({product:“MongoDB”,
type:“Document Database”})
>
> db.collection.findOne()
{
“_id”
: ObjectId(“5106c1c2fc629bfe52792e86”),
“product”
: “MongoDB”
“type”
: “Document Database”
}
NoSQL Trends
Google Search

LinkedIn Job Skills
MongoDB
Competitor 1
Competitor 2
Competitor 3
Competitor 4
Competitor 5

MongoDB

Competitor 2

Competitor 1

Competitor 4

Competitor 3

All Others

Jaspersoft Big Data Index

Indeed.com Trends
Top Job Trends

Direct Real-Time Downloads
MongoDB
Competitor 1
Competitor 2
Competitor 3

1.HTML 5
2.MongoDB
3.iOS
4.Android
5.Mobile Apps
6.Puppet
7.Hadoop
8.jQuery
9.PaaS
10.Social Media
Datenmanipulation
Terminologie
RDBMS
Tabelle / View
Zeile
Index
Join
Fremdschlüssel
Partition

MongoDB
➜
➜
➜
➜

Collection
Dokument
Index
Eingebettetes
Dokument
➜ Referenziertes
Dokument
➜ Shard
Let’s have a look…
Anlegen einer Datenbank
// Anzeigen aller Datenbanken
> show dbs
digg 0.078125GB
enron 1.49951171875GB
// Wechsel in eine Datenbank
> use blog
// Erneutes Anzeigen aller Datenbanken
> show dbs
digg 0.078125GB
enron 1.49951171875GB
Anlegen einer Collection I
// Anzeigen aller Collections
> show collections
// Einfügen eines Benutzers
> db.user.insert(
{ name : “Sheldon“,
mail : “sheldon@bigbang.com“ }
)

Beim Einfügen erfolgt kein Feedback über
den Erfolg der Operation, Abfrage über:
db.runCommand( { getLastError: 1} )
Anlegen einer Collection II
// Anzeigen aller Collections
> show collections
system.indexes
user
// Anzeigen aller Datenbanken
> show dbs
blog 0.0625GB
digg 0.078125GB
enron 1.49951171875GB

Datenbank und Collection
werden automatisch beim
ersten Insert anlegt.
Lesen aus einer Collection
// Anzeigen des ersten Dokuments
> db.user.findOne()
{
"_id" : ObjectId("516684a32f391f3c2fcb80ed"),
"name" : "Sheldon",
"mail" : "sheldon@bigbang.com"
}
// Alle Dokumente einer Collection anzeigen
> db.user.find()
{
"_id" : ObjectId("516684a32f391f3c2fcb80ed"),
"name" : "Sheldon",
"mail" : "sheldon@bigbang.com"
}
Filtern von Dokumenten
// Filtern von bestimmten Dokumenten
> db.user.find( { name : ”Penny” } )
{
"_id" : ObjectId("5166a9dc2f391f3c2fcb80f1"),
"name" : "Penny",
"mail" : "penny@bigbang.com"
}
// Nur bestimmte Felder anzeigen
> db.user.find( { name : ”Penny” },
{_id: 0, mail : 1} )
{ "mail" : "sheldon@bigbang.com" }
_id
•

_id ist der primäre Schlüssel in MongoDB

•

Index auf _id wird automatisch erzeugt

•

Wenn nicht anders angegeben, handelt es
sich dabei um eine ObjectId

•

_id kann auch selbst beim Einfügen von
Dokumenten vergeben werden, jeder
einzigartige unveränderbare Wert kann
dabei verwendet werden
ObjectId
•

Eine ObjectId ist ein spezieller 12 Byte
Wert

•

Ihre Einzigartigkeit über den gesamten
Cluster ist durch die Zusammensetzung
garantiert:
ObjectId("50804d0bd94ccab2da652599")
|-------------||---------||-----||----------|
ts
mac pid inc
Cursor
// Benutzen eines Cursors für die Dokumente
> var myCursor = db.user.find( )
// Nächstes Dokument holen und Mail anzeigen
> var myDocument =
myCursor.hasNext() ? myCursor.next() : null;
> if (myDocument) { printjson(myDocument.mail); }
// Restliche Dokumente anzeigen
> myCursor.forEach(printjson);

In der Shell werden per Default
20 Dokumente angezeigt.
Logische Verknüpfungen
// Oder-Verknüpfung
> db.user.find(
{$or : [ { name : “Sheldon“ },
{ mail : amy@bigbang.com }
]
})
// Und-Verknüpfung
> db.user.find(
{$and : [ { name : “Sheldon“ },
{ mail : amy@bigbang.com }
]
})
Ergebnismengen anpassen
// Sortieren von Dokumenten
> db.user.find().sort( { name : 1 } ) // Aufsteigend
> db.user.find().sort( { name : -1 } ) // Absteigend
// Ergebnismenge limitieren
> db.user.find().limit(3)
// Ergebnisdokumente überspringen
> db.user.find().skip(2)
// Kombination der Methoden
> db.user.find().skip(2).limit(3)
Update von Dokumenten I
// Update der Mail-Adresse (So bitte nicht!)
> db.user.update( { name : “Sheldon“ },
{ mail : “sheldon@howimetyourmother.com“ }
)
// Anzeige des Updates
db.user.findOne()
{
"_id" : ObjectId("516684a32f391f3c2fcb80ed"),
"mail" : "sheldon@howimetyourmother.com"
}

Aufpassen beim Update von
Dokumenten!
Löschen von Dokumenten
// Löschen des Dokuments
> db.user.remove(
{ mail : “sheldon@howimetyourmother.com“ }
)
// Löschen aller Dokumente
> db.user.remove()
// Löschen von Dokumenten mittels Bedingung
> db.user.remove(
{ mail : /.*mother.com$/ } )
// Löschen nur des ersten passenden Dokuments
> db.user.remove( { mail : /.*.com$/ }, true )
Update von Dokumenten II
// Update der Mail-Adresse (Jetzt aber richtig!)
> db.user.update( { name : “Sheldon“ },
{ $set : {
mail : “sheldon@howimetyourmother.com“
}})
// Anzeige des Updates
db.user.find(name : “Sheldon“)
{
"_id" : ObjectId("5166ba122f391f3c2fcb80f5"),
"mail" : "sheldon@howimetyourmother.com",
"name" : "Sheldon"
}
Hinzufügen zu Arrays
// Hinzufügen eines Arrays
> db.user.update( {name : “Sheldon“ },
{ $set : {enemies :
[ { name : “Wil Wheaton“ },
{ name : “Barry Kripke“ }
]
}})
// Hinzufügen eines Wertes zum Array
> db.user.update( { name : “Sheldon“},
{ $push : {enemies :
{ name : “Leslie Winkle“}
}})
Löschen aus Arrays
// Löschen eines Wertes aus dem Array
> db.user.update( { name : “Sheldon“ },
{$pull : {enemies :
{name : “Barry Kripke“ }
}})
// Löschen des kompletten Feldes
> db.user.update( {name : “Sheldon“},
{$unset : {enemies : 1}}
)
Einfügen eines Subdokuments
// Hinzufügen eines Subdokuments
> db.user.update( { name : “Sheldon“}, {
$set : { mother :{ name : “Mary Cooper“,
residence : “Galveston, Texas“,
religion : “Evangelical Christian“ }}})
{
"_id" : ObjectId("5166cf162f391f3c2fcb80f7"),
"mail" : "sheldon@bigbang.com",
"mother" : {
"name" : "Mary Cooper",
"residence" : "Galveston, Texas",
"religion" : "Evangelical Christian"
},
"name" : "Sheldon"
}
Abfragen auf Subdokumenten
// Abfrage des Namens der Mutter
> db.user.find( { name : “Sheldon“},
{“mother.name“ : 1 } )
{
"_id" : ObjectId("5166cf162f391f3c2fcb80f7"),
"mother" : {
"name" : "Mary Cooper"
}
}

Zusammengesetzte Feldnamen
müssen in “…“ stehen!
Übersicht über alle UpdateOperatoren
Für Felder:
$inc
$rename
$set
$unset
Bitweise:
$bit
Isolation:
$isolated

Für Arrays:
$addToSet
$pop
$pullAll
$pull
$pushAll
$push
$each (Modifier)
$slice (Modifier)
$sort (Modifier)
Dokumentation

Create
http://docs.mongodb.org/manual/core/create/

Read
http://docs.mongodb.org/manual/core/read/

Update
http://docs.mongodb.org/manual/core/update/

Delete
http://docs.mongodb.org/manual/core/delete/
Das Aggregation Framework
•

Wurde eingeführt, um Aggregationen
ohne Map/Reduce berechnen zu können

•

Framework von Methoden & Operatoren
– Deklarativ
– Kein eigener JavaScript-Code mehr nötig
– Framework kann erweitert werden

•

Implementiert in C++
– Overhead der JavaScript-Engine wird vermieden
– Höhere Performance
Aggregation Pipeline
Pipeline
Operator
Pipeline
Operator
Pipeline
Operator

{
document
}

Ergebnis
{
sum: 337
avg: 24,53
min: 2
max : 99
}
Aggregation Pipeline
•

Verarbeitet einen Strom von Dokumenten
– Eingabe ist eine Collection
– Ausgabe ist ein Ergebnisdokument

•

Aneinanderreihung von PipelineOperatoren
– Jede Stufe filtert oder transformiert die Dokumente
– Ausgabedokumente einer Stufe sind die Eingabe-

dokumente der nächsten Stufe
Aufruf
> db.tweets.aggregate(
{ $pipeline_operator_1
{ $pipeline_operator_2
{ $pipeline_operator_3
{ $pipeline_operator_4
...
);

},
},
},
},
Pipeline Operatoren
// Alte Bekannte* // Neue Freunde
$match
$sort
$limit
$skip
* Aus der Abfragefunktionalität

$project
$group
$unwind
Aggregation Framework I
// Collection mit Tweets
{
"_id" : ObjectId("4fb9fb91d066d657de8d6f39"),
"text" : "I can't wait for #BoardwalkEmpire",
"in_reply_to_status_id" : null,
"retweet_count" : null,
"contributors" : null,
"created_at" : "Thu Sep 02 18:11:24 +0000 2010",
…
"user" : {
"friends_count" : 204,
…
"followers_count" : 24,
"id" : 64054560,
…
},
…}
Aggregation Framework II
// Finde die Top-3-Twitterer nach Followern
> db.tweets.aggregate(
{ $project : {name : "$user.name",
follower_count : "$user.followers_count"}},
{ $group : {_id : {name : "$name"},
follower_count : {$max : "$follower_count"}}},
{ $sort : {follower_count : -1}},
{ $limit: 3}
);
Aggregation Framework III
// Finde die Top-3-Links aus Tweets
> db.tweets.aggregate(
{ $project : {_id: 0, inhalt_des_tweets :
"$text", links : "$entities.urls.url" } },
{ $unwind : "$links" },
{ $group : { _id : "$links",
anzahl : {$sum : 1} } },
{ $sort : {anzahl : -1} },
{ $limit : 3 }
);
Was ist Map/Reduce?
•

Programmiermodel aus der funktionalen
Welt

•

Framework zur
– parallelen Verarbeitung
– von großen Datenmengen
– mittels verteilter Systeme

•

Populär geworden durch Google
– Wird zur Berechnung des Suchindex verwendet,

welcher Seiten zu Keywords zuordnet (Page Rank)
– http://research.google.com/archive/mapreduce.html
Map/Reduce mit MongoDB
MongoDB

map()

Daten

group(k)

emit(k,v)
Shard 1

• Iteriert über
alle
Dokumente

sort(k)

Shard 2

…
Shard n

reduce(k, values)
finalize(k, v)
k, v

k, v
•
•

Input = Output
Kann mehrfach laufen
Word Count: Problemstellung
INPUT
{
MongoDB
uses
MapReduce
}

{
There is a
map phase
}

{
There is a
reduce
phase
}

MAPPER

GROUP/SORT

REDUCER

OUTPUT

a: 2
is: 2
map: 1

Problem:
Wie häufig kommt
ein Wort in allen
Dokumenten vor?

mapreduce: 1
mongodb: 1
phase: 2

reduce: 1
there: 2
uses: 1
Word Count: Tweets
// Beispiel: Twitter-Datenbank mit Tweets
> db.tweets.findOne()
{
"_id" : ObjectId("4fb9fb91d066d657de8d6f38"),
"text" : "RT @RevRunWisdom: The bravest thing that men do is
love women #love",
"created_at" : "Thu Sep 02 18:11:24 +0000 2010",
…
"user" : {
"friends_count" : 0,
"profile_sidebar_fill_color" : "252429",
"screen_name" : "RevRunWisdom",
"name" : "Rev Run",
},
…
Word Count: Map Funktion
// Map Funktion mit Bereinigung der Daten
map = function() {
this.text.split(' ').forEach(function(word) {
// Entfernen von Whitespace
word = word.replace(/s/g, "");
// Entfernen alle Non-Word-Characters
word = word.replace(/W/gm,"");
// Finally emit the cleaned up word
if(word != "") {
emit(word, 1)
}
});
};
Word Count: Reduce Funktion
// Reduce Funktion
reduce = function(key, values) {
return values.length;
};
Word Count: Aufruf
// Anzeigen des Ergebnisses in der Konsole
> db.tweets.mapReduce(map, reduce, { out : { inline : 1 } } );
// Speichern des Ergebnisses in einer Collection
> db.tweets.mapReduce(map, reduce, { out : "tweets_word_count"} );
{
"result" : "tweets_word_count",
"timeMillis" : 19026,
"counts" : {
"input" : 53641,
"emit" : 559217,
"reduce" : 102057,
"output" : 131003
},
"ok" : 1,
}
Word Count: Ergebnis
// Ausgeben der 10 häufigsten Wörter in Tweets
> db.tweets_word_count.find().sort({"value" : -1}).limit(10)
{
{
{
{
{
{
{
{
{
{

"_id"
"_id"
"_id"
"_id"
"_id"
"_id"
"_id"
"_id"
"_id"
"_id"

:
:
:
:
:
:
:
:
:
:

"Miley", "value" : 31 }
"mil", "value" : 31 }
"andthenihitmydougie", "value" : 30 }
"programa", "value" : 30 }
"Live", "value" : 29 }
"Super", "value" : 29 }
"cabelo", "value" : 29 }
"listen", "value" : 29 }
"Call", "value" : 28 }
"DA", "value" : 28 }
Indexing
Indexe in MongoDB sind B-Trees
Abfragen, Einfügen und Löschen:
O(log(n))
Fehlende oder nicht
optimale Indexe sind
das häufigste
vermeidbare MongoDB
Performance-Problem
Wie lege ich Indexe an?
// Anlegen eines Index, wenn er noch nicht existiert
> db.recipes.createIndex({ main_ingredient: 1 })

// Der Client merkt sich den Index und wirft keinen Fehler
> db.recipes.ensureIndex({ main_ingredient: 1 })

* 1 für aufsteigend, -1 für absteigend
Was kann indexiert werden?
// Mehrere Felder (Compound Key Indexes)
> db.recipes.ensureIndex({
main_ingredient: 1,
calories: -1
})
// Arrays mit Werten (Multikey Indexes)
{
name: 'Chicken Noodle Soup’,
ingredients : ['chicken', 'noodles']
}
> db.recipes.ensureIndex({ ingredients: 1 })
Was kann indexiert werden?
// Subdokumente
{
name : 'Apple Pie',
contributor: {
name: 'Joe American',
id: 'joea123'
}
}
db.recipes.ensureIndex({ 'contributor.id': 1 })
db.recipes.ensureIndex({ 'contributor': 1 })
Wie verwalte ich Indexe?
// Auflisten aller Indexe einer Collection
> db.recipes.getIndexes()
> db.recipes.getIndexKeys()

// Löschen eines Index
> db.recipes.dropIndex({ ingredients: 1 })

// Löschen und Neuerzeugung aller Indexe
db.recipes.reIndex()

// Defaultindex auf _id
Weitere Optionen
•

Unique Indexe
– Nur eindeutige Werte erlaubt

•

Sparse Indexe
– Für Felder, die nicht in allen Dokumenten

vorkommen

•

Geospatial Indexe
– Zur Modellierung von Geoinformationen

•

TTL Collections
– Verfallen nach x Sekunden
Unique Indexe
// Der Name eines Rezepts muss eindeutig sein
> db.recipes.ensureIndex( { name: 1 }, { unique: true } )

// Erzwingen eines Index auf einer Collection mit nicht eindeutigen
// Namen – Die Duplikate werden gelöscht
> db.recipes.ensureIndex(
{ name: 1 },
{ unique: true, dropDups: true }
)

* dropDups bitte mit sehr viel Vorsicht anwenden!
Sparse Indexe
// Nur Dokumente mit dem Feld calories werden indexiert
> db.recipes.ensureIndex(
{ calories: -1 },
{ sparse: true }
)
// Kombination mit einem Unique Index möglich
> db.recipes.ensureIndex(
{ name: 1 , calories: -1 },
{ unique: true, sparse: true }
)
* Fehlende Felder werden im Index als null gespeichert
Geospatial Indexe
// Hinzufügen von Längen- und Breitengraden
{
name: ‚codecentric Frankfurt’,
loc: [ 50.11678, 8.67206]
}
// Indexierung der Koordinaten
> db.locations.ensureIndex( { loc : '2d' } )

// Abfrage nach Orten in der Nähe von codecentric Frankfurt
> db.locations.find({
loc: { $near: [ 50.1, 8.7 ] }
})
TTL Collections
// Die Dokumente müssen ein Datum des Typs BSON UTC haben
{ ' submitted_date ' : ISODate('2012-10-12T05:24:07.211Z'), … }

// Dokumente werden automatisch nach 'expireAfterSeconds'
// Sekunden gelöscht
> db.recipes.ensureIndex(
{ submitted_date: 1 },
{ expireAfterSeconds: 3600 }
)
Limitierungen von Indexen
•

Collections können nicht mehr als 64 Indexe haben.

•

Indexschlüssel können nicht größer als 1024 Byte
sein.

•

Der Name eines Index inklusive Namespace muss
kleiner als 128 Zeichen sein.

•

Abfragen können nur einen Index verwenden
– Ausnahme: Abfragen mit $or

•

Indexe verbrauchen Speichern und verlangsamen
das Schreiben von Daten
Optimierung von Indexen
Vorgehensweise
1. Langsame Abfragen identifizieren
2. Mittels explain() mehr über die

langsame Abfrage herausfinden
3. Anlegen der Indexe auf den

abgefragten Feldern
4. Optimierung der Abfragen anhand

der verwendeten Indexe
1. Langsame Abfragen
identifizieren
> db.setProfilingLevel( n , slowms=100ms )

n=0: Profiler abgeschaltet
n=1: Protokollieren aller Abfragen langsamer als slowms
n=2: Protokollieren aller Operationen

> db.system.profile.find()

* Die Collection profile ist eine Capped Collection und hat daher eine feste
Anzahl von Einträgen
2. Benutzung von explain()
> db.recipes.find( { calories:
{ $lt : 40 } }
).explain( )
{
"cursor" : "BasicCursor" ,
"n" : 42,
"nscannedObjects” : 53641
"nscanned" : 53641,
...
"millis" : 252,
...
}
* Keine Verwendung von Plänen aus dem Cache und erneuten Ausführungen
2. Metriken des Executionplans I
• Cursor
– Der Typ des Cursors. BasicCursor bedeutet, dass

kein Index benutzt wurde

• n
– Die Anzahl der passenden Dokumente

• nscannedObjects
– Die Anzahl der gescannten Dokumente

• nscanned
– Die Anzahl der untersuchten Einträge

(Indexeinträge oder Dokumente)
2. Metriken des Executionplans II
• millis
– Ausführungszeit der Abfrage

• Komplette Referenz unter
– http://docs.mongodb.org/manual/reference/explain

Das Verhältnis der gescannten
zu den gefundenen
Dokumenten sollte möglichst
nahe an 1 sein!
3. Anlegen der Indexe auf den
abgefragten Feldern
4. Optimierung der Abfragen
anhand der verwendeten Indexe
// Bei folgendem Index…
> db.collection.ensureIndex({ a:1, b:1 , c:1, d:1 })
//
//
>
>

… können die folgenden Sortieroperationen und Abfragen den
Index benutzen
db.collection.find( ).sort({ a:1 })
db.collection.find( ).sort({ a:1, b:1 })

> db.collection.find({ a:4 }).sort({ a:1, b:1 })
> db.collection.find({ b:5 }).sort({ a:1, b:1 })
4. Optimierung der Abfragen
anhand der verwendeten Indexe
// Bei folgendem Index…
> db.collection.ensureIndex({ a:1, b:1, c:1, d:1 })

// … können diese Abfragen ihn nicht verwenden
> db.collection.find( ).sort({ b: 1 })
> db.collection.find({ b: 5 }).sort({ b: 1 })
4. Optimierung der Abfragen
anhand der verwendeten Indexe
// Bei folgendem Index…
> db.recipes.ensureIndex({ main_ingredient: 1, name: 1 })
// … verwendet diese Abfrage nur Felder des Index
> db.recipes.find(
{ main_ingredient: 'chicken’ },
{ _id: 0, name: 1 }
)
// Das Feld indexOnly bei explain() zeigt dies an
> db.recipes.find(
{ main_ingredient: 'chicken' },
{ _id: 0, name: 1 }
).explain()
{
"indexOnly": true,
}
Index manuell angeben
// MongoDB mitteilen, welcher Index verwendet werden soll
> db.recipes.find({
calories: { $lt: 1000 } }
).hint({ _id: 1 })

// Die Verwendung von Indexen ausschalten (z.B. zur Performance// messung
> db.recipes.find(
{ calories: { $lt: 1000 } }
).hint({ $natural: 1 })
Häufige Stolperfallen
bei Indexen
Mehrere Index verwenden
// MongoDB kann nur einen Index pro Abfrage verwenden
> db.collection.ensureIndex({ a: 1 })
> db.collection.ensureIndex({ b: 1 })

// Nur einer der beiden obigen Indexe wird verwendet
> db.collection.find({ a: 3, b: 4 })
Zusammengesetzte Indexe
// Zusammengesetzte Indexe sind im Allgemeinen sehr effektiv
> db.collection.ensureIndex({ a: 1, b: 1, c: 1 })

// Aber nur wenn die Abfrage ein Präfix des Indexes ist…

// Diese Abfrage kann den Index nicht effektiv verwenden
db.collection.find({ c: 2 })

// …diese Abfrage hingegen schon
db.collection.find({ a: 3, b: 5 })
Indexe mit geringer
Selektivität
// Folgendes Feld hat nur sehr wenige eindeutige Werte
> db.collection.distinct('status’)
[ 'new', 'processed' ]
// Ein Index auf diesem Feld bringt nur sehr wenig
> db.collection.ensureIndex({ status: 1 })
> db.collection.find({ status: 'new' })
// Besser ist ein zusammengesetzter Index zusammen mit einem
// anderen Feld
> db.collection.ensureIndex({ status: 1, created_at: -1 })
> db.collection.find(
{ status: 'new' }
).sort({ created_at: -1 })
Reguläre Ausdrücke & Indexe
> db.users.ensureIndex({ username: 1 })

// Abfragen mit regulären Ausdrücken, die linksgebunden sind
// können den Index verwenden
> db.users.find({ username: /^joe smith/ })

// Generische Abfragen mit regulären Ausdrücken hingegen nicht…
> db.users.find({username: /smith/ })

// Ebenso nicht schreibungsunabhängige Abfragen…
> db.users.find({ username: /Joe/i })
Negation
// Bei Negationen können Indexe nicht verwendet werden
> db.things.ensureIndex({ x: 1 })
// z.B. bei Abfragen mit not equal
> db.things.find({ x: { $ne: 3 } })
// …oder Abfragen mit not in
> db.things.find({ x: { $nin: [2, 3, 4 ] } })
// …oder Abfragen mit dem $not Operator
> db.people.find({ name: { $not: 'John Doe' } })
Konsistenz beim Schreiben
und Lesen von Daten
Starke Konsistenz
Verzögerte Konsistenz
Write Concern - Schreibmodi
•

Bestätigung durch das Netzwerk

•

Bestätigung durch MongoDB

•

Bestätigung durch das Journal

•

Bestätigung durch Secondaries

•

Bestätigung durch Tagging
Bestätigung durch das Netzwerk
„Fire and forget“
Bestätigung durch MongoDB
Wait for Error
Bestätigung durch das Journal
Wait for Journal Sync
Bestätigung durch Secondaries
Wait for Replication
Tagging beim Schreiben
•

Verfügbar seit Version 2.0

•

Ermöglicht stärkere Kontrolle woher Daten
gelesen und wohin geschrieben werden

•

Jeder Knoten kann mehrere Tags haben
– tags: {dc: "ny"}
– tags: {dc: "ny", subnet: „192.168", rack: „row3rk7"}

•

Erlaubt das Anlegen für Regeln für das Write
Concern pro Replikaset

•

Anpassung der Regeln ohne Codeänderung
Beispiel für Tagging
{
_id : "mySet",
members : [
{_id : 0, host : "A", tags : {"dc": "ny"}},
{_id : 1, host : "B", tags : {"dc": "ny"}},
{_id : 2, host : "C", tags : {"dc": "sf"}},
{_id : 3, host : "D", tags : {"dc": "sf"}},
{_id : 4, host : "E", tags : {"dc": "cloud"}}],
settings : {
getLastErrorModes : {
allDCs : {"dc" : 3},
someDCs : {"dc" : 2}} }
}
> db.blogs.insert({...})
> db.runCommand({getLastError : 1, w : "someDCs"})
Bestätigung durch alle Datenzentren

Wait for Replication (Tagging)
Setzen des Write Concerns
// Wait for network acknowledgement
> db.runCommand( { getLastError: 1, w: 0 } )
// Wait for error (Default)
> db.runCommand( { getLastError: 1, w: 1 } )
// Wait for journal sync
> db.runCommand( { getLastError: 1, w: 1, j: "true" } )
// Wait for replication
> db.runCommand( { getLastError: 1, w: “majority" } ) // Mehrheit
> db.runCommand( { getLastError: 1, w: 3 } ) // # der Secondaries
Modi zum Lesen von Daten
(Seit Version 2.2)
•

Nur Primary

(primary)

•

Primary bevorzugt

(primaryPreferred)

•

Nur Secondaries

(secondary)

•

Secondaries bevorzugt

(secondaryPreferred)

•

Nähester Knoten

(Nearest)

Falls mehr als ein Knoten möglich ist, wird immer der
näheste Knoten zum Lesen der Daten verwendet. (Alle
Modi außer Primary)
Read

Nur Primary
primary
Read
Read

Primary bevorzugt
primaryPreferred
Read

Read

Nur Secondaries
secondary
Read

Read
Read

Secondaries bevorzugt
secondaryPreferred
Read

Read
Read

Nähester Knoten
nearest
Tagging beim Lesen
•

Ermöglicht eine individuelle Kontrolle
woher Daten gelesen werden
– z.B. { "disk": "ssd", "use": "reporting" }

•

Lässt sich mit den Standard-Lese-Modi
kombinieren
– Außer dem Modus „Nur Primary“
Setzen der Read Preference
// Nur Primary
> cursor.setReadPref( “primary" )
// Primary bevorzugt
> cursor.setReadPref( “primaryPreferred" )
….
// Nur Secondaries mit Tagging
> cursor.setReadPref( “secondary“, [ rack : 2 ] )

Aufruf der Methode auf dem Cursor muss
vor dem Lesen der Dokumente erfolgen
Java API & Frameworks
Übersicht
Jongo

Spring Data
MongoDB

Morphia

Hibernate
OGM

JPA

JDBC

MongoDB Java Driver
MongoDB
MongoDB Java Treiber
MongoDB Treiber
•

Ein Wire Protokoll für alle
Programmiersprachen

•

Eine Implementierung des Treibers pro
Sprache

•

Hauptaufgaben:
– Konvertierung der sprachspezifischen

Datenstrukturen nach BSON
– Generierung der ObjectId für das Feld _id
MongoDB Java Treiber
•

Ein JAR ohne weitere Abhängigkeiten:
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>2.11.3</version>
</dependency>

Verfügbar auf Github:
https://github.com/mongodb/mongo-java-driver
Verbindungsaufbau
import com.mongodb.MongoClient;
// Default: localhost:27017
mongo = new MongoClient();
// Replica set
mongo = new MongoClient(Arrays.asList(
new ServerAddress("replicant01", 10001),
new ServerAddress("replicant02", 10002),
new ServerAddress("replicant03", 10003)
));
// Sharding: mongos server
mongo = new MongoClient("mongos01", 4711);
Zugriff auf Datenbank und
Collection
import com.mongodb.DB;
import com.mongodb.DBCollection;
DB db = mongo.getDB("test");
DBCollection collection =
db.getCollection("foo");
Dokument einfügen
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
// insert document
DBObject doc = new BasicDBObject();
doc.put("date", new Date());
doc.put("i", 42);
collection.insert(doc);
Dokumente abfragen
import com.mongodb.DBCursor;
DBCursor cursor;
cursor = collection.find(); // all documents
// documents w/ {i: 42}
cursor = collection.find(
new BasicDBObject("i", 42) );
document = cursor.next();
...
Beispiel: Bestellung

> db.order.find( {"items.quantity": ? } )
Beispiel: Bestellung I
DB db = mongo.getDB("test");
DBCollection collection = db.getCollection("order");
DBObject order;
List<DBObject> items = new ArrayList<DBObject>();
DBObject item;
// order
order = new BasicDBObject();
order.put("date", new Date());
order.put("custInfo" , „Sheldon Cooper");
// items
item = new BasicDBObject();
item.put("quantity", 1);
item.put("price", 47.11);
item.put("desc", "Item #1");
items.add(item);
item = new BasicDBObject();
item.put("quantity", 2);
item.put("price", 42.0);
item.put("desc", "Item #2");
items.add(item);
order.put("items", items);
collection.insert(order);
Beispiel: Bestellung II
DB db = mongo.getDB("test");
DBCollection collection = db.getCollection("order");
DBObject query;
DBObject document;
DBCursor cursor;
query = new BasicDBObject("items.quantity", 2);
cursor = collection.find(query);
while ( cursor.hasNext() ) {
document = cursor.next();
println(document);
}
Jongo
Kurzüberblick über Jongo
Entwickler
Lizenz
Dokumentation
Hauptmerkmale

Benoît Guérout, Yves Amsellem
Apache License, Version 2.0
http://jongo.org/
• Object/Document Mapping
• Eigene Query API
Query in Java as in Mongo Shell
Jongo: Object Mapping
public class Order {
private ObjectId id;
private Date date;
@JsonProperty("custInfo") private String customerInfo;
List<Item> items;
…
}
public class Item {
private int quantity;
private double price;
@JsonProperty("desc") private String description;
…
}
Jongo: Abfragen
// Java driver API
MongoClient mc = new MongoClient();
DB db = mc.getDB("odm_jongo");
// Jongo API entry point
Jongo jongo = new Jongo(db);
MongoCollection orders = jongo.getCollection("order");
// no DAO needed
Iterable<Order> result =
orders.find("{"items.quantity": #}", 2).as(Order.class);
// supports projection
Iterable<X> result =
orders.find().fields("{_id:0, date:1,
custInfo:1}").as(X.class);
Morphia
Kurzüberblick über Morphia

Entwickler
Lizenz
Dokumentation

Scott Hernandez, James Green
Apache License, Version 2.0
https://github.com/jmkgreen/morph
ia/wiki/Overview
Hauptmerkmale • Object/Document Mapping
• Eigene Query API
• Unterstützung für DAO‘s
Morphia: Object Mapping
public class Order {
@Id private ObjectId id;
private Date date;
@Property("custInfo") private String customerInfo;
@Embedded List<Item> items;
...
}
public class Item {
private int quantity;
private double price;
@Property("desc") private String description;
...
}
Morphia: Abfragen
public class OrderDao extends BasicDAO<Order, ObjectId> {
List<Order> findByItemsQuantity(int quantity) {
return
find( createQuery().filter("items.quantity", quantity))
.asList();
}
List<Order> findByItemsPriceGreaterThan(double price) {
return
find(
createQuery().field("items.price").greaterThan(price) )
.asList();
}
…
}
Morphia: Eigene Syntax für
Abfragen
Morphia

Mongo Query

=
!=, <>
>, <, >=,<=
in, nin
elem
…

$eq
$neq
$gt, $lt, $gte, $lte
$in, $nin
$elemMatch
….
Spring Data MongoDB
Kurzüberblick über
Spring Data MongoDB
Hersteller
Lizenz
Dokumentation

VMware / SpringSource
Apache License, Version 2.0
http://www.springsource.org/spring
-data/mongodb
Hauptmerkmale • Repository Support
• Object/Document Mapping
• Templating
Spring Data
CrudRepository
Spring Data
JPA

PagingAndSortingRepository
Spring Data
Neo4j

MongoReposito
ry

GraphRepos itory

MongoT em plate

JpaRepository

Spring Data
MongoDB

Neo4 jTemplate
Em bedded

JPA
JDBC
RDBMS

Spring Data
…

RES T

Mongo Java
Driver
Mongo
DB

Neo4j

…

Einheitliche Architektur für relationale
Datenbanken sowie für unterstützte NoSQL-Stores
Spring Data MongoDB
•

Repository Support
– Abfragen werden aus den Methodensignaturen erstellt
– Annotationen für Abfragen

•

Object-Document-Mapping
– Annotationen: @Document, @Field, @Index, …
– Klassen werden auf Collections gemappt, Javaobjekte auf

Dokumente

•

Templating
–
–
–
–

Abstraktion der Ressourcen
Konfigurierbarkeit der Verbindungen zu MongoDB
Abdeckung des Lebenszyklus einer Collection
Unterstützung für Map/Reduce & Aggregation Framework
Spring Data MongoDB:
Konfiguration
<!-- Connection to MongoDB server -->
<mongo:db-factory host="localhost" port="27017" dbname="test" />
<!-- MongoDB Template -->
<bean id="mongoTemplate,
class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg name="mongoDbFactory" ref="mongoDbFactory"/>
</bean>
<!-- Package w/ automagic repositories -->
<mongo:repositories base-package="mongodb" />
Spring Data MongoDB:
Template
<mongo:mongo host="${mongo.host}" port="${mongo.port}">
<mongo:options
connections-per-host="${mongo.connectionsPerHost}„
threads-allowed-to-block-for-connection
multiplier="${mongo.threadsAllowedToBlockForConnectionMultiplier}„
connect-timeout="${mongo.connectTimeout}„
max-wait-time="${mongo.maxWaitTime}„
auto-connect-retry="${mongo.autoConnectRetry}„
socket-keep-alive="${mongo.socketKeepAlive}„
socket-timeout="${mongo.socketTimeout}„
slave-ok="${mongo.slaveOk}„
write-number="1„
write-timeout="0„
write-fsync="true"/>
</mongo:mongo>
<mongo:db-factory dbname= "test" mongo-ref="mongo"/>
Spring Data MongoDB:
Object Mapping
public class Order {
@Id private String id;
private Date date;
@Field("custInfo") private String customerInfo;
List<Item> items; ...
}
public class Item {
private int quantity;
private double price;
@Field("desc") private String description;
...
}
Spring Data MongoDB:
Repository Support
public interface OrderRepository extends
MongoRepository<Order, String> {
List<Order> findByItemsQuantity(int
quantity);
List<Order>
findByItemsPriceGreaterThan(double
price);
}
Spring Data MongoDB:
Zusätzliche Unterstützung für…
•

Map/Reduce & das Aggregation Framework

•

Das Management von Indexen

•

Grosse Dateien mittels GridFS

•

Geoinformatische Indexe und Abfragen

•

Optimistisches Locking
Hibernate OGM
Kurzüberblick über
Hibernate OGM MongoDB
Hersteller
Lizenz
Dokumentation

JBoss / Redhat
GNU LGPL, Version 2.1
http://www.hibernate.org/subproject
s/ogm.html
Hauptmerkmale • JPA API (Teilweise)
• JPQL Query Language
Hibernate OGM
• Implementiert ein Subset der JPA API
• JP-QL Anfragen werden in native

Datenbankabfragen übersetzt
• Unterstützt Infinispan, EhCache,

MongoDB
Architektur von
Hibernate OGM

Source:
http://docs.jboss.org/hibernate/ogm/4.0/reference/en-US/html/ogm-architecture.html#d0e409
Hibernate OGM MongoDB:
Konfiguration
<persistence version="2.0" …>
<persistence-unit name="primary">
<provider>org.hibernate.ogm.jpa.HibernateOgmPersistence</provider>
<class>hibernate.Order</class>
<class>hibernate.Item</class>
<properties>
<property name="hibernate.ogm.datastore.provider"
value="org.hibernate.ogm.datastore.mongodb.impl.MongoDBDatastorePr
ovider"/>
<property name="hibernate.ogm.mongodb.database" value=„odm"/>
<property name="hibernate.ogm.mongodb.host" value=„localhost"/>
<property name="hibernate.ogm.mongodb.port" value=„27017"/>
</properties>
</persistence-unit>
</persistence>
Hibernate OGM MongoDB:
Object Mapping
@Entity
@NamedQuery(
name="byItemsQuantity",
query = "SELECT o FROM Order o JOIN o.items i WHERE i.quantity = :quantity"
)
public class Order {
@GeneratedValue(generator = "uuid")
@GenericGenerator(name = "uuid", strategy = "uuid2")
@Id private String id;
private Date date;
@Column(name = "custInfo") private String customerInfo;
@ElementCollection
private List<Item> items;
@Embeddable
public class Item {
private int quantity;
private double price;
@Column(name="desc") private String description;
...
Hibernate OGM MongoDB:
Aktueller Status
•

Frühes Beta-Stadium

• Aktuell nur Speichern / Mergen /

Löschen von Daten möglich
• Noch keine Unterstützung für

Abfragen
• Benutzt eine relationale API
Not yet ready for prime time…
Empfehlung
Was sollte ich einsetzen?
- „Ready for production“

JPA

Hibernate
OGM

Spring Data
MongoDB

- Aktive Community

- Ältestes Framework
- Nicht so mächtig wie Spring

- Frühes Betastadium
- Diskrepanz in API

Morphia
Der „bessere“ Treiber

Jongo
JDBC

MongoDB Java Driver
- „Ready for production“
- Von MongoDB Inc. unterstützt
MongoDB
Getting started…

One more thing…
MongoDB User Group

https://www.xing.com/net/mongodb-ffm/
http://www.meetup.com/Frankfurt-Rhine-Main-MongoDB-User-Group/
So Long, and Thanks for All the Fish!

Weitere ähnliche Inhalte

Was ist angesagt?

Back to Basics-Webinar 5: Einführung in das Aggregation-Framework
Back to Basics-Webinar 5: Einführung in das Aggregation-FrameworkBack to Basics-Webinar 5: Einführung in das Aggregation-Framework
Back to Basics-Webinar 5: Einführung in das Aggregation-FrameworkMongoDB
 
Morphia, Spring Data & Co
Morphia, Spring Data & CoMorphia, Spring Data & Co
Morphia, Spring Data & CoTobias Trelle
 
Einfuehrung in Elasticsearch
Einfuehrung in ElasticsearchEinfuehrung in Elasticsearch
Einfuehrung in ElasticsearchFlorian Hopf
 
Einführung in Elasticsearch
Einführung in ElasticsearchEinführung in Elasticsearch
Einführung in ElasticsearchFlorian Hopf
 
2012-01-31 NoSQL in .NET
2012-01-31 NoSQL in .NET2012-01-31 NoSQL in .NET
2012-01-31 NoSQL in .NETJohannes Hoppe
 
Back to Basics – Webinar 3: Schema-Design: Denken in Dokumenten
Back to Basics – Webinar 3: Schema-Design: Denken in DokumentenBack to Basics – Webinar 3: Schema-Design: Denken in Dokumenten
Back to Basics – Webinar 3: Schema-Design: Denken in DokumentenMongoDB
 
Apache Cassandra - Einführung
Apache Cassandra - EinführungApache Cassandra - Einführung
Apache Cassandra - EinführungAndreas Finke
 
Hadoop 2.0 - The Next Level
Hadoop 2.0 - The Next LevelHadoop 2.0 - The Next Level
Hadoop 2.0 - The Next LevelSascha Dittmann
 
OOP 2013: Praktische Einführung in MongoDB
OOP 2013: Praktische Einführung in MongoDBOOP 2013: Praktische Einführung in MongoDB
OOP 2013: Praktische Einführung in MongoDBTobias Trelle
 
MongoDB Munich 2012: Spring Data MongoDB
MongoDB Munich 2012: Spring Data MongoDBMongoDB Munich 2012: Spring Data MongoDB
MongoDB Munich 2012: Spring Data MongoDBTobias Trelle
 
Warum 'ne Datenbank, wenn wir Elasticsearch haben?
Warum 'ne Datenbank, wenn wir Elasticsearch haben?Warum 'ne Datenbank, wenn wir Elasticsearch haben?
Warum 'ne Datenbank, wenn wir Elasticsearch haben?Jodok Batlogg
 
Tech Talk Cassandra
Tech Talk CassandraTech Talk Cassandra
Tech Talk Cassandraadesso AG
 
Einführung in Elasticsearch
Einführung in ElasticsearchEinführung in Elasticsearch
Einführung in ElasticsearchFlorian Hopf
 
The Hadoop Connection
The Hadoop ConnectionThe Hadoop Connection
The Hadoop Connectioninovex GmbH
 
Python crash-kurs
Python crash-kursPython crash-kurs
Python crash-kursklausbremer
 
MapRecude: The Hadoop Connection
MapRecude: The Hadoop ConnectionMapRecude: The Hadoop Connection
MapRecude: The Hadoop Connectionvesparun
 
Praesentation TYPO3Camp Berlin Speed mit Extbase
Praesentation TYPO3Camp Berlin Speed mit ExtbasePraesentation TYPO3Camp Berlin Speed mit Extbase
Praesentation TYPO3Camp Berlin Speed mit ExtbaseStefan Frömken
 
Back to Basics - Webinar 6: Produktivsetzung einer Anwendung
Back to Basics - Webinar 6: Produktivsetzung einer AnwendungBack to Basics - Webinar 6: Produktivsetzung einer Anwendung
Back to Basics - Webinar 6: Produktivsetzung einer AnwendungMongoDB
 

Was ist angesagt? (20)

Back to Basics-Webinar 5: Einführung in das Aggregation-Framework
Back to Basics-Webinar 5: Einführung in das Aggregation-FrameworkBack to Basics-Webinar 5: Einführung in das Aggregation-Framework
Back to Basics-Webinar 5: Einführung in das Aggregation-Framework
 
Morphia, Spring Data & Co
Morphia, Spring Data & CoMorphia, Spring Data & Co
Morphia, Spring Data & Co
 
Einfuehrung in Elasticsearch
Einfuehrung in ElasticsearchEinfuehrung in Elasticsearch
Einfuehrung in Elasticsearch
 
Einführung in Elasticsearch
Einführung in ElasticsearchEinführung in Elasticsearch
Einführung in Elasticsearch
 
2012-01-31 NoSQL in .NET
2012-01-31 NoSQL in .NET2012-01-31 NoSQL in .NET
2012-01-31 NoSQL in .NET
 
Back to Basics – Webinar 3: Schema-Design: Denken in Dokumenten
Back to Basics – Webinar 3: Schema-Design: Denken in DokumentenBack to Basics – Webinar 3: Schema-Design: Denken in Dokumenten
Back to Basics – Webinar 3: Schema-Design: Denken in Dokumenten
 
Apache Cassandra - Einführung
Apache Cassandra - EinführungApache Cassandra - Einführung
Apache Cassandra - Einführung
 
Hadoop 2.0 - The Next Level
Hadoop 2.0 - The Next LevelHadoop 2.0 - The Next Level
Hadoop 2.0 - The Next Level
 
OOP 2013: Praktische Einführung in MongoDB
OOP 2013: Praktische Einführung in MongoDBOOP 2013: Praktische Einführung in MongoDB
OOP 2013: Praktische Einführung in MongoDB
 
MongoDB Munich 2012: Spring Data MongoDB
MongoDB Munich 2012: Spring Data MongoDBMongoDB Munich 2012: Spring Data MongoDB
MongoDB Munich 2012: Spring Data MongoDB
 
Warum 'ne Datenbank, wenn wir Elasticsearch haben?
Warum 'ne Datenbank, wenn wir Elasticsearch haben?Warum 'ne Datenbank, wenn wir Elasticsearch haben?
Warum 'ne Datenbank, wenn wir Elasticsearch haben?
 
Einführung CouchDB
Einführung CouchDBEinführung CouchDB
Einführung CouchDB
 
Tech Talk Cassandra
Tech Talk CassandraTech Talk Cassandra
Tech Talk Cassandra
 
Einführung in Elasticsearch
Einführung in ElasticsearchEinführung in Elasticsearch
Einführung in Elasticsearch
 
The Hadoop Connection
The Hadoop ConnectionThe Hadoop Connection
The Hadoop Connection
 
Python crash-kurs
Python crash-kursPython crash-kurs
Python crash-kurs
 
MapRecude: The Hadoop Connection
MapRecude: The Hadoop ConnectionMapRecude: The Hadoop Connection
MapRecude: The Hadoop Connection
 
Praesentation TYPO3Camp Berlin Speed mit Extbase
Praesentation TYPO3Camp Berlin Speed mit ExtbasePraesentation TYPO3Camp Berlin Speed mit Extbase
Praesentation TYPO3Camp Berlin Speed mit Extbase
 
Back to Basics - Webinar 6: Produktivsetzung einer Anwendung
Back to Basics - Webinar 6: Produktivsetzung einer AnwendungBack to Basics - Webinar 6: Produktivsetzung einer Anwendung
Back to Basics - Webinar 6: Produktivsetzung einer Anwendung
 
Datenbankoptimierung
DatenbankoptimierungDatenbankoptimierung
Datenbankoptimierung
 

Andere mochten auch

First meetup of the MongoDB User Group Frankfurt
First meetup of the MongoDB User Group FrankfurtFirst meetup of the MongoDB User Group Frankfurt
First meetup of the MongoDB User Group FrankfurtUwe Printz
 
Hadoop 2 - Beyond MapReduce
Hadoop 2 - Beyond MapReduceHadoop 2 - Beyond MapReduce
Hadoop 2 - Beyond MapReduceUwe Printz
 
Introduction to the Hadoop Ecosystem (SEACON Edition)
Introduction to the Hadoop Ecosystem (SEACON Edition)Introduction to the Hadoop Ecosystem (SEACON Edition)
Introduction to the Hadoop Ecosystem (SEACON Edition)Uwe Printz
 
Map/Confused? A practical approach to Map/Reduce with MongoDB
Map/Confused? A practical approach to Map/Reduce with MongoDBMap/Confused? A practical approach to Map/Reduce with MongoDB
Map/Confused? A practical approach to Map/Reduce with MongoDBUwe Printz
 
Introduction to the Hadoop Ecosystem (codemotion Edition)
Introduction to the Hadoop Ecosystem (codemotion Edition)Introduction to the Hadoop Ecosystem (codemotion Edition)
Introduction to the Hadoop Ecosystem (codemotion Edition)Uwe Printz
 
Introduction to the Hadoop Ecosystem (IT-Stammtisch Darmstadt Edition)
Introduction to the Hadoop Ecosystem (IT-Stammtisch Darmstadt Edition)Introduction to the Hadoop Ecosystem (IT-Stammtisch Darmstadt Edition)
Introduction to the Hadoop Ecosystem (IT-Stammtisch Darmstadt Edition)Uwe Printz
 
Lightning Talk: Agility & Databases
Lightning Talk: Agility & DatabasesLightning Talk: Agility & Databases
Lightning Talk: Agility & DatabasesUwe Printz
 
Hadoop 2 - More than MapReduce
Hadoop 2 - More than MapReduceHadoop 2 - More than MapReduce
Hadoop 2 - More than MapReduceUwe Printz
 
Introduction to the Hadoop Ecosystem (FrOSCon Edition)
Introduction to the Hadoop Ecosystem (FrOSCon Edition)Introduction to the Hadoop Ecosystem (FrOSCon Edition)
Introduction to the Hadoop Ecosystem (FrOSCon Edition)Uwe Printz
 
Hadoop 2 - Going beyond MapReduce
Hadoop 2 - Going beyond MapReduceHadoop 2 - Going beyond MapReduce
Hadoop 2 - Going beyond MapReduceUwe Printz
 
Hadoop & Security - Past, Present, Future
Hadoop & Security - Past, Present, FutureHadoop & Security - Past, Present, Future
Hadoop & Security - Past, Present, FutureUwe Printz
 
Hadoop meets Agile! - An Agile Big Data Model
Hadoop meets Agile! - An Agile Big Data ModelHadoop meets Agile! - An Agile Big Data Model
Hadoop meets Agile! - An Agile Big Data ModelUwe Printz
 
Introduction to the Hadoop Ecosystem with Hadoop 2.0 aka YARN (Java Serbia Ed...
Introduction to the Hadoop Ecosystem with Hadoop 2.0 aka YARN (Java Serbia Ed...Introduction to the Hadoop Ecosystem with Hadoop 2.0 aka YARN (Java Serbia Ed...
Introduction to the Hadoop Ecosystem with Hadoop 2.0 aka YARN (Java Serbia Ed...Uwe Printz
 

Andere mochten auch (14)

First meetup of the MongoDB User Group Frankfurt
First meetup of the MongoDB User Group FrankfurtFirst meetup of the MongoDB User Group Frankfurt
First meetup of the MongoDB User Group Frankfurt
 
Hadoop 2 - Beyond MapReduce
Hadoop 2 - Beyond MapReduceHadoop 2 - Beyond MapReduce
Hadoop 2 - Beyond MapReduce
 
Introduction to the Hadoop Ecosystem (SEACON Edition)
Introduction to the Hadoop Ecosystem (SEACON Edition)Introduction to the Hadoop Ecosystem (SEACON Edition)
Introduction to the Hadoop Ecosystem (SEACON Edition)
 
Map/Confused? A practical approach to Map/Reduce with MongoDB
Map/Confused? A practical approach to Map/Reduce with MongoDBMap/Confused? A practical approach to Map/Reduce with MongoDB
Map/Confused? A practical approach to Map/Reduce with MongoDB
 
Introduction to the Hadoop Ecosystem (codemotion Edition)
Introduction to the Hadoop Ecosystem (codemotion Edition)Introduction to the Hadoop Ecosystem (codemotion Edition)
Introduction to the Hadoop Ecosystem (codemotion Edition)
 
Introduction to the Hadoop Ecosystem (IT-Stammtisch Darmstadt Edition)
Introduction to the Hadoop Ecosystem (IT-Stammtisch Darmstadt Edition)Introduction to the Hadoop Ecosystem (IT-Stammtisch Darmstadt Edition)
Introduction to the Hadoop Ecosystem (IT-Stammtisch Darmstadt Edition)
 
Lightning Talk: Agility & Databases
Lightning Talk: Agility & DatabasesLightning Talk: Agility & Databases
Lightning Talk: Agility & Databases
 
Hadoop 2 - More than MapReduce
Hadoop 2 - More than MapReduceHadoop 2 - More than MapReduce
Hadoop 2 - More than MapReduce
 
Introduction to the Hadoop Ecosystem (FrOSCon Edition)
Introduction to the Hadoop Ecosystem (FrOSCon Edition)Introduction to the Hadoop Ecosystem (FrOSCon Edition)
Introduction to the Hadoop Ecosystem (FrOSCon Edition)
 
Hadoop 2 - Going beyond MapReduce
Hadoop 2 - Going beyond MapReduceHadoop 2 - Going beyond MapReduce
Hadoop 2 - Going beyond MapReduce
 
Hadoop & Security - Past, Present, Future
Hadoop & Security - Past, Present, FutureHadoop & Security - Past, Present, Future
Hadoop & Security - Past, Present, Future
 
Hadoop meets Agile! - An Agile Big Data Model
Hadoop meets Agile! - An Agile Big Data ModelHadoop meets Agile! - An Agile Big Data Model
Hadoop meets Agile! - An Agile Big Data Model
 
Apache Spark
Apache SparkApache Spark
Apache Spark
 
Introduction to the Hadoop Ecosystem with Hadoop 2.0 aka YARN (Java Serbia Ed...
Introduction to the Hadoop Ecosystem with Hadoop 2.0 aka YARN (Java Serbia Ed...Introduction to the Hadoop Ecosystem with Hadoop 2.0 aka YARN (Java Serbia Ed...
Introduction to the Hadoop Ecosystem with Hadoop 2.0 aka YARN (Java Serbia Ed...
 

Ähnlich wie MongoDB für Java Programmierer (JUGKA, 11.12.13)

JSF und JPA effizient kombinieren (W-JAX 2011)
JSF und JPA effizient kombinieren (W-JAX 2011)JSF und JPA effizient kombinieren (W-JAX 2011)
JSF und JPA effizient kombinieren (W-JAX 2011)Michael Kurz
 
2012-05-14 NoSQL in .NET - mit Redis und MongoDB
2012-05-14 NoSQL in .NET - mit Redis und MongoDB2012-05-14 NoSQL in .NET - mit Redis und MongoDB
2012-05-14 NoSQL in .NET - mit Redis und MongoDBJohannes Hoppe
 
2012-05-10 - UG Karlsruhe: NoSQL in .NET - mit Redis und MongoDB
2012-05-10 - UG Karlsruhe: NoSQL in .NET - mit Redis und MongoDB2012-05-10 - UG Karlsruhe: NoSQL in .NET - mit Redis und MongoDB
2012-05-10 - UG Karlsruhe: NoSQL in .NET - mit Redis und MongoDBJohannes Hoppe
 
Einführung in NoSQL-Datenbanken
Einführung in NoSQL-DatenbankenEinführung in NoSQL-Datenbanken
Einführung in NoSQL-DatenbankenTobias Trelle
 
Back to Basics German 2: Erstellen Sie Ihre erste Anwendung in MongoDB
Back to Basics German 2: Erstellen Sie Ihre erste Anwendung in MongoDBBack to Basics German 2: Erstellen Sie Ihre erste Anwendung in MongoDB
Back to Basics German 2: Erstellen Sie Ihre erste Anwendung in MongoDBMongoDB
 
mongoDB im Einsatz - Grundlagen
mongoDB im Einsatz - GrundlagenmongoDB im Einsatz - Grundlagen
mongoDB im Einsatz - Grundlageninovex GmbH
 
Domain Driven Design in Rails
Domain Driven Design in RailsDomain Driven Design in Rails
Domain Driven Design in RailsAngelo Maron
 
Java Code Quality: Gute Software braucht guten Code - Regeln für verständlich...
Java Code Quality: Gute Software braucht guten Code - Regeln für verständlich...Java Code Quality: Gute Software braucht guten Code - Regeln für verständlich...
Java Code Quality: Gute Software braucht guten Code - Regeln für verständlich...GFU Cyrus AG
 
Fanstatic pycon.de 2012
Fanstatic pycon.de 2012Fanstatic pycon.de 2012
Fanstatic pycon.de 2012Daniel Havlik
 
Yes zu NoSQL mit MongoDB für .NET-Entwickler
Yes zu NoSQL mit MongoDB für .NET-EntwicklerYes zu NoSQL mit MongoDB für .NET-Entwickler
Yes zu NoSQL mit MongoDB für .NET-EntwicklerGregor Biswanger
 
Apache CouchDB at PHPUG Karlsruhe, Germany (Jan 27th 2009)
Apache CouchDB at PHPUG Karlsruhe, Germany (Jan 27th 2009)Apache CouchDB at PHPUG Karlsruhe, Germany (Jan 27th 2009)
Apache CouchDB at PHPUG Karlsruhe, Germany (Jan 27th 2009)Nils Adermann
 
Dokumentation schreiben kann spass machen
Dokumentation schreiben kann spass machenDokumentation schreiben kann spass machen
Dokumentation schreiben kann spass machenSebastian Hempel
 
Elasticsearch & docker mit logstash, jdbc und ruby
Elasticsearch & docker mit logstash, jdbc und rubyElasticsearch & docker mit logstash, jdbc und ruby
Elasticsearch & docker mit logstash, jdbc und rubySchanzDieter
 
Microservices mit Rust
Microservices mit RustMicroservices mit Rust
Microservices mit RustJens Siebert
 
Datenbankzugriff mit der Java Persistence Api
Datenbankzugriff mit der Java Persistence ApiDatenbankzugriff mit der Java Persistence Api
Datenbankzugriff mit der Java Persistence ApiChristian Baranowski
 
DB-Schema-Evolution mit LiquiBase
DB-Schema-Evolution mit LiquiBaseDB-Schema-Evolution mit LiquiBase
DB-Schema-Evolution mit LiquiBasegedoplan
 
HashiTalks: DACH - Die Verwendung von IaC im DevOps Prozess
HashiTalks: DACH - Die Verwendung von IaC im DevOps ProzessHashiTalks: DACH - Die Verwendung von IaC im DevOps Prozess
HashiTalks: DACH - Die Verwendung von IaC im DevOps ProzessJochen Zehnder
 
Schlanke Webarchitekturen nicht nur mit JSF 2 und CDI
Schlanke Webarchitekturen nicht nur mit JSF 2 und CDISchlanke Webarchitekturen nicht nur mit JSF 2 und CDI
Schlanke Webarchitekturen nicht nur mit JSF 2 und CDIadesso AG
 
Docker-Images mit vorinstallierter Instanz einer Oracle-DB
Docker-Images mit vorinstallierter Instanz einer Oracle-DBDocker-Images mit vorinstallierter Instanz einer Oracle-DB
Docker-Images mit vorinstallierter Instanz einer Oracle-DBPeter Ramm
 

Ähnlich wie MongoDB für Java Programmierer (JUGKA, 11.12.13) (20)

JSF und JPA effizient kombinieren (W-JAX 2011)
JSF und JPA effizient kombinieren (W-JAX 2011)JSF und JPA effizient kombinieren (W-JAX 2011)
JSF und JPA effizient kombinieren (W-JAX 2011)
 
2012-05-14 NoSQL in .NET - mit Redis und MongoDB
2012-05-14 NoSQL in .NET - mit Redis und MongoDB2012-05-14 NoSQL in .NET - mit Redis und MongoDB
2012-05-14 NoSQL in .NET - mit Redis und MongoDB
 
2012-05-10 - UG Karlsruhe: NoSQL in .NET - mit Redis und MongoDB
2012-05-10 - UG Karlsruhe: NoSQL in .NET - mit Redis und MongoDB2012-05-10 - UG Karlsruhe: NoSQL in .NET - mit Redis und MongoDB
2012-05-10 - UG Karlsruhe: NoSQL in .NET - mit Redis und MongoDB
 
Einführung in NoSQL-Datenbanken
Einführung in NoSQL-DatenbankenEinführung in NoSQL-Datenbanken
Einführung in NoSQL-Datenbanken
 
Back to Basics German 2: Erstellen Sie Ihre erste Anwendung in MongoDB
Back to Basics German 2: Erstellen Sie Ihre erste Anwendung in MongoDBBack to Basics German 2: Erstellen Sie Ihre erste Anwendung in MongoDB
Back to Basics German 2: Erstellen Sie Ihre erste Anwendung in MongoDB
 
mongoDB im Einsatz - Grundlagen
mongoDB im Einsatz - GrundlagenmongoDB im Einsatz - Grundlagen
mongoDB im Einsatz - Grundlagen
 
Domain Driven Design in Rails
Domain Driven Design in RailsDomain Driven Design in Rails
Domain Driven Design in Rails
 
Java Code Quality: Gute Software braucht guten Code - Regeln für verständlich...
Java Code Quality: Gute Software braucht guten Code - Regeln für verständlich...Java Code Quality: Gute Software braucht guten Code - Regeln für verständlich...
Java Code Quality: Gute Software braucht guten Code - Regeln für verständlich...
 
Fanstatic pycon.de 2012
Fanstatic pycon.de 2012Fanstatic pycon.de 2012
Fanstatic pycon.de 2012
 
Yes zu NoSQL mit MongoDB für .NET-Entwickler
Yes zu NoSQL mit MongoDB für .NET-EntwicklerYes zu NoSQL mit MongoDB für .NET-Entwickler
Yes zu NoSQL mit MongoDB für .NET-Entwickler
 
Apache CouchDB at PHPUG Karlsruhe, Germany (Jan 27th 2009)
Apache CouchDB at PHPUG Karlsruhe, Germany (Jan 27th 2009)Apache CouchDB at PHPUG Karlsruhe, Germany (Jan 27th 2009)
Apache CouchDB at PHPUG Karlsruhe, Germany (Jan 27th 2009)
 
Dokumentation schreiben kann spass machen
Dokumentation schreiben kann spass machenDokumentation schreiben kann spass machen
Dokumentation schreiben kann spass machen
 
Node.js
Node.jsNode.js
Node.js
 
Elasticsearch & docker mit logstash, jdbc und ruby
Elasticsearch & docker mit logstash, jdbc und rubyElasticsearch & docker mit logstash, jdbc und ruby
Elasticsearch & docker mit logstash, jdbc und ruby
 
Microservices mit Rust
Microservices mit RustMicroservices mit Rust
Microservices mit Rust
 
Datenbankzugriff mit der Java Persistence Api
Datenbankzugriff mit der Java Persistence ApiDatenbankzugriff mit der Java Persistence Api
Datenbankzugriff mit der Java Persistence Api
 
DB-Schema-Evolution mit LiquiBase
DB-Schema-Evolution mit LiquiBaseDB-Schema-Evolution mit LiquiBase
DB-Schema-Evolution mit LiquiBase
 
HashiTalks: DACH - Die Verwendung von IaC im DevOps Prozess
HashiTalks: DACH - Die Verwendung von IaC im DevOps ProzessHashiTalks: DACH - Die Verwendung von IaC im DevOps Prozess
HashiTalks: DACH - Die Verwendung von IaC im DevOps Prozess
 
Schlanke Webarchitekturen nicht nur mit JSF 2 und CDI
Schlanke Webarchitekturen nicht nur mit JSF 2 und CDISchlanke Webarchitekturen nicht nur mit JSF 2 und CDI
Schlanke Webarchitekturen nicht nur mit JSF 2 und CDI
 
Docker-Images mit vorinstallierter Instanz einer Oracle-DB
Docker-Images mit vorinstallierter Instanz einer Oracle-DBDocker-Images mit vorinstallierter Instanz einer Oracle-DB
Docker-Images mit vorinstallierter Instanz einer Oracle-DB
 

Mehr von Uwe Printz

Hadoop 3.0 - Revolution or evolution?
Hadoop 3.0 - Revolution or evolution?Hadoop 3.0 - Revolution or evolution?
Hadoop 3.0 - Revolution or evolution?Uwe Printz
 
Hadoop 3.0 - Revolution or evolution?
Hadoop 3.0 - Revolution or evolution?Hadoop 3.0 - Revolution or evolution?
Hadoop 3.0 - Revolution or evolution?Uwe Printz
 
Hadoop Operations - Best practices from the field
Hadoop Operations - Best practices from the fieldHadoop Operations - Best practices from the field
Hadoop Operations - Best practices from the fieldUwe Printz
 
Welcome to Hadoop2Land!
Welcome to Hadoop2Land!Welcome to Hadoop2Land!
Welcome to Hadoop2Land!Uwe Printz
 
MongoDB for Coder Training (Coding Serbia 2013)
MongoDB for Coder Training (Coding Serbia 2013)MongoDB for Coder Training (Coding Serbia 2013)
MongoDB for Coder Training (Coding Serbia 2013)Uwe Printz
 
Introduction to Twitter Storm
Introduction to Twitter StormIntroduction to Twitter Storm
Introduction to Twitter StormUwe Printz
 

Mehr von Uwe Printz (6)

Hadoop 3.0 - Revolution or evolution?
Hadoop 3.0 - Revolution or evolution?Hadoop 3.0 - Revolution or evolution?
Hadoop 3.0 - Revolution or evolution?
 
Hadoop 3.0 - Revolution or evolution?
Hadoop 3.0 - Revolution or evolution?Hadoop 3.0 - Revolution or evolution?
Hadoop 3.0 - Revolution or evolution?
 
Hadoop Operations - Best practices from the field
Hadoop Operations - Best practices from the fieldHadoop Operations - Best practices from the field
Hadoop Operations - Best practices from the field
 
Welcome to Hadoop2Land!
Welcome to Hadoop2Land!Welcome to Hadoop2Land!
Welcome to Hadoop2Land!
 
MongoDB for Coder Training (Coding Serbia 2013)
MongoDB for Coder Training (Coding Serbia 2013)MongoDB for Coder Training (Coding Serbia 2013)
MongoDB for Coder Training (Coding Serbia 2013)
 
Introduction to Twitter Storm
Introduction to Twitter StormIntroduction to Twitter Storm
Introduction to Twitter Storm
 

MongoDB für Java Programmierer (JUGKA, 11.12.13)

  • 2. About me Big Data Nerd Hadoop Trainer MongoDB Author Photography Enthusiast Travelpirate
  • 3. About us is a bunch of… Big Data Nerds Agile Ninjas Continuous Delivery Gurus Join us! Enterprise Java Specialists Performance Geeks
  • 4. Agenda • Buzzword Bingo • Überblick über MongoDB • Datenmanipulation • Indexing • Konsistenz beim Schreiben und Lesen von Daten • Java API & Frameworks
  • 7. Klassifizierung von NoSQL Key-Value Stores Column Stores K V K V 1 K V K V 1 1 K V Graph Databases 1 1 1 1 1 1 1 1 Document Stores _id _id _id
  • 10. Die klassische Definition • The 3 V’s of Big Data Volume Velocity •Variety
  • 11. «Big Data» != Hadoop
  • 20. Das CAP Theorem Availability Jede Anfrage bekommt eine Antwort Consistency Alle Knoten haben jederzeit die gleichen Informationen Partition Tolerance Trotz Knotenausfall funktioniert das System
  • 21. Überblick über NoSQL Systeme Availability Jeder Client kann immer schreiben und lesen C onsistency Alle Knoten haben jederzeit die gleichen Informationen Partition Tolerance Trotz Knotenausfall funktioniert das System
  • 24. ACID vs. BASE 1983 Atomicity RDBMS Consistency Isolation Durability
  • 25. ACID vs. BASE ACID ist ein gutes Konzept, aber es ist kein in Stein gemeißeltes Gesetz!
  • 26. ACID vs. BASE Basically Available Soft State 2008 NoSQL Eventually consistent
  • 27. ACID vs. BASE ACID BASE - - Starke Konsistenz Isolation Zwei-Phasen-Commit Komplexe Entwicklung Zuverlässiger Schwache Konsistenz Verfügbarkeit "Fire-and-forget" Leichtere Entwicklung Schneller
  • 29. MongoDB ist eine … • Dokumenten-basierte • Open Source • Performante • Flexible • Skalierbare • Hochverfügbare • Funktionsreiche …Datenbank
  • 30. Dokumenten-basierte Datenbank • Nicht im Sinne einer Datenbank für PDFoder Worddokumente…
  • 31. Open Source Datenbank • MongoDB ist ein Open Source Projekt • Auf GitHub – https://github.com/mongodb/mongo • Steht unter der AGPL Lizenz • Gestartet und gesponsert von MongoDB Inc. (früher: 10gen) • Kommerzielle Lizenzen sind verfügbar • Jeder darf mitmachen! – https://jira.mongodb.org
  • 33. Flexibles Schema MongoDB RDBMS { _id : ObjectId("4c4ba5e5e8aabf3"), employee_name: "Dunham, Justin", department : "Marketing", title : "Product Manager, Web", report_up: "Neray, Graham", pay_band: “C", benefits : [ { type : "Health", plan : "PPO Plus" }, { type : "Dental", plan : "Standard" } ] }
  • 34. Skalierbarkeit Auto-Sharding • Erhöhung der Kapazität wenn nötig • Ausgelegt für Commodity Hardware • Funktioniert mit Cloud-Architekturen
  • 35. Hochverfügbarkeit • Automatische Replikation und Failover • Unterstützung für mehrere Datenzentren • Ausgelegt auf möglichst einfachen Betrieb • Beständigkeit und Konsistenz der Daten
  • 41. Treiber & Shell Treiber verfügbar für die populärsten Programmiersprachen und Frameworks Java JavaScript Python Shell zur Interaktion mit der Datenbank Ruby Perl Haskell > db.collection.insert({product:“MongoDB”, type:“Document Database”}) > > db.collection.findOne() { “_id” : ObjectId(“5106c1c2fc629bfe52792e86”), “product” : “MongoDB” “type” : “Document Database” }
  • 42. NoSQL Trends Google Search LinkedIn Job Skills MongoDB Competitor 1 Competitor 2 Competitor 3 Competitor 4 Competitor 5 MongoDB Competitor 2 Competitor 1 Competitor 4 Competitor 3 All Others Jaspersoft Big Data Index Indeed.com Trends Top Job Trends Direct Real-Time Downloads MongoDB Competitor 1 Competitor 2 Competitor 3 1.HTML 5 2.MongoDB 3.iOS 4.Android 5.Mobile Apps 6.Puppet 7.Hadoop 8.jQuery 9.PaaS 10.Social Media
  • 45. Let’s have a look…
  • 46. Anlegen einer Datenbank // Anzeigen aller Datenbanken > show dbs digg 0.078125GB enron 1.49951171875GB // Wechsel in eine Datenbank > use blog // Erneutes Anzeigen aller Datenbanken > show dbs digg 0.078125GB enron 1.49951171875GB
  • 47. Anlegen einer Collection I // Anzeigen aller Collections > show collections // Einfügen eines Benutzers > db.user.insert( { name : “Sheldon“, mail : “sheldon@bigbang.com“ } ) Beim Einfügen erfolgt kein Feedback über den Erfolg der Operation, Abfrage über: db.runCommand( { getLastError: 1} )
  • 48. Anlegen einer Collection II // Anzeigen aller Collections > show collections system.indexes user // Anzeigen aller Datenbanken > show dbs blog 0.0625GB digg 0.078125GB enron 1.49951171875GB Datenbank und Collection werden automatisch beim ersten Insert anlegt.
  • 49. Lesen aus einer Collection // Anzeigen des ersten Dokuments > db.user.findOne() { "_id" : ObjectId("516684a32f391f3c2fcb80ed"), "name" : "Sheldon", "mail" : "sheldon@bigbang.com" } // Alle Dokumente einer Collection anzeigen > db.user.find() { "_id" : ObjectId("516684a32f391f3c2fcb80ed"), "name" : "Sheldon", "mail" : "sheldon@bigbang.com" }
  • 50. Filtern von Dokumenten // Filtern von bestimmten Dokumenten > db.user.find( { name : ”Penny” } ) { "_id" : ObjectId("5166a9dc2f391f3c2fcb80f1"), "name" : "Penny", "mail" : "penny@bigbang.com" } // Nur bestimmte Felder anzeigen > db.user.find( { name : ”Penny” }, {_id: 0, mail : 1} ) { "mail" : "sheldon@bigbang.com" }
  • 51. _id • _id ist der primäre Schlüssel in MongoDB • Index auf _id wird automatisch erzeugt • Wenn nicht anders angegeben, handelt es sich dabei um eine ObjectId • _id kann auch selbst beim Einfügen von Dokumenten vergeben werden, jeder einzigartige unveränderbare Wert kann dabei verwendet werden
  • 52. ObjectId • Eine ObjectId ist ein spezieller 12 Byte Wert • Ihre Einzigartigkeit über den gesamten Cluster ist durch die Zusammensetzung garantiert: ObjectId("50804d0bd94ccab2da652599") |-------------||---------||-----||----------| ts mac pid inc
  • 53. Cursor // Benutzen eines Cursors für die Dokumente > var myCursor = db.user.find( ) // Nächstes Dokument holen und Mail anzeigen > var myDocument = myCursor.hasNext() ? myCursor.next() : null; > if (myDocument) { printjson(myDocument.mail); } // Restliche Dokumente anzeigen > myCursor.forEach(printjson); In der Shell werden per Default 20 Dokumente angezeigt.
  • 54. Logische Verknüpfungen // Oder-Verknüpfung > db.user.find( {$or : [ { name : “Sheldon“ }, { mail : amy@bigbang.com } ] }) // Und-Verknüpfung > db.user.find( {$and : [ { name : “Sheldon“ }, { mail : amy@bigbang.com } ] })
  • 55. Ergebnismengen anpassen // Sortieren von Dokumenten > db.user.find().sort( { name : 1 } ) // Aufsteigend > db.user.find().sort( { name : -1 } ) // Absteigend // Ergebnismenge limitieren > db.user.find().limit(3) // Ergebnisdokumente überspringen > db.user.find().skip(2) // Kombination der Methoden > db.user.find().skip(2).limit(3)
  • 56. Update von Dokumenten I // Update der Mail-Adresse (So bitte nicht!) > db.user.update( { name : “Sheldon“ }, { mail : “sheldon@howimetyourmother.com“ } ) // Anzeige des Updates db.user.findOne() { "_id" : ObjectId("516684a32f391f3c2fcb80ed"), "mail" : "sheldon@howimetyourmother.com" } Aufpassen beim Update von Dokumenten!
  • 57. Löschen von Dokumenten // Löschen des Dokuments > db.user.remove( { mail : “sheldon@howimetyourmother.com“ } ) // Löschen aller Dokumente > db.user.remove() // Löschen von Dokumenten mittels Bedingung > db.user.remove( { mail : /.*mother.com$/ } ) // Löschen nur des ersten passenden Dokuments > db.user.remove( { mail : /.*.com$/ }, true )
  • 58. Update von Dokumenten II // Update der Mail-Adresse (Jetzt aber richtig!) > db.user.update( { name : “Sheldon“ }, { $set : { mail : “sheldon@howimetyourmother.com“ }}) // Anzeige des Updates db.user.find(name : “Sheldon“) { "_id" : ObjectId("5166ba122f391f3c2fcb80f5"), "mail" : "sheldon@howimetyourmother.com", "name" : "Sheldon" }
  • 59. Hinzufügen zu Arrays // Hinzufügen eines Arrays > db.user.update( {name : “Sheldon“ }, { $set : {enemies : [ { name : “Wil Wheaton“ }, { name : “Barry Kripke“ } ] }}) // Hinzufügen eines Wertes zum Array > db.user.update( { name : “Sheldon“}, { $push : {enemies : { name : “Leslie Winkle“} }})
  • 60. Löschen aus Arrays // Löschen eines Wertes aus dem Array > db.user.update( { name : “Sheldon“ }, {$pull : {enemies : {name : “Barry Kripke“ } }}) // Löschen des kompletten Feldes > db.user.update( {name : “Sheldon“}, {$unset : {enemies : 1}} )
  • 61. Einfügen eines Subdokuments // Hinzufügen eines Subdokuments > db.user.update( { name : “Sheldon“}, { $set : { mother :{ name : “Mary Cooper“, residence : “Galveston, Texas“, religion : “Evangelical Christian“ }}}) { "_id" : ObjectId("5166cf162f391f3c2fcb80f7"), "mail" : "sheldon@bigbang.com", "mother" : { "name" : "Mary Cooper", "residence" : "Galveston, Texas", "religion" : "Evangelical Christian" }, "name" : "Sheldon" }
  • 62. Abfragen auf Subdokumenten // Abfrage des Namens der Mutter > db.user.find( { name : “Sheldon“}, {“mother.name“ : 1 } ) { "_id" : ObjectId("5166cf162f391f3c2fcb80f7"), "mother" : { "name" : "Mary Cooper" } } Zusammengesetzte Feldnamen müssen in “…“ stehen!
  • 63. Übersicht über alle UpdateOperatoren Für Felder: $inc $rename $set $unset Bitweise: $bit Isolation: $isolated Für Arrays: $addToSet $pop $pullAll $pull $pushAll $push $each (Modifier) $slice (Modifier) $sort (Modifier)
  • 65. Das Aggregation Framework • Wurde eingeführt, um Aggregationen ohne Map/Reduce berechnen zu können • Framework von Methoden & Operatoren – Deklarativ – Kein eigener JavaScript-Code mehr nötig – Framework kann erweitert werden • Implementiert in C++ – Overhead der JavaScript-Engine wird vermieden – Höhere Performance
  • 67. Aggregation Pipeline • Verarbeitet einen Strom von Dokumenten – Eingabe ist eine Collection – Ausgabe ist ein Ergebnisdokument • Aneinanderreihung von PipelineOperatoren – Jede Stufe filtert oder transformiert die Dokumente – Ausgabedokumente einer Stufe sind die Eingabe- dokumente der nächsten Stufe
  • 68. Aufruf > db.tweets.aggregate( { $pipeline_operator_1 { $pipeline_operator_2 { $pipeline_operator_3 { $pipeline_operator_4 ... ); }, }, }, },
  • 69. Pipeline Operatoren // Alte Bekannte* // Neue Freunde $match $sort $limit $skip * Aus der Abfragefunktionalität $project $group $unwind
  • 70. Aggregation Framework I // Collection mit Tweets { "_id" : ObjectId("4fb9fb91d066d657de8d6f39"), "text" : "I can't wait for #BoardwalkEmpire", "in_reply_to_status_id" : null, "retweet_count" : null, "contributors" : null, "created_at" : "Thu Sep 02 18:11:24 +0000 2010", … "user" : { "friends_count" : 204, … "followers_count" : 24, "id" : 64054560, … }, …}
  • 71. Aggregation Framework II // Finde die Top-3-Twitterer nach Followern > db.tweets.aggregate( { $project : {name : "$user.name", follower_count : "$user.followers_count"}}, { $group : {_id : {name : "$name"}, follower_count : {$max : "$follower_count"}}}, { $sort : {follower_count : -1}}, { $limit: 3} );
  • 72. Aggregation Framework III // Finde die Top-3-Links aus Tweets > db.tweets.aggregate( { $project : {_id: 0, inhalt_des_tweets : "$text", links : "$entities.urls.url" } }, { $unwind : "$links" }, { $group : { _id : "$links", anzahl : {$sum : 1} } }, { $sort : {anzahl : -1} }, { $limit : 3 } );
  • 73. Was ist Map/Reduce? • Programmiermodel aus der funktionalen Welt • Framework zur – parallelen Verarbeitung – von großen Datenmengen – mittels verteilter Systeme • Populär geworden durch Google – Wird zur Berechnung des Suchindex verwendet, welcher Seiten zu Keywords zuordnet (Page Rank) – http://research.google.com/archive/mapreduce.html
  • 74. Map/Reduce mit MongoDB MongoDB map() Daten group(k) emit(k,v) Shard 1 • Iteriert über alle Dokumente sort(k) Shard 2 … Shard n reduce(k, values) finalize(k, v) k, v k, v • • Input = Output Kann mehrfach laufen
  • 75. Word Count: Problemstellung INPUT { MongoDB uses MapReduce } { There is a map phase } { There is a reduce phase } MAPPER GROUP/SORT REDUCER OUTPUT a: 2 is: 2 map: 1 Problem: Wie häufig kommt ein Wort in allen Dokumenten vor? mapreduce: 1 mongodb: 1 phase: 2 reduce: 1 there: 2 uses: 1
  • 76. Word Count: Tweets // Beispiel: Twitter-Datenbank mit Tweets > db.tweets.findOne() { "_id" : ObjectId("4fb9fb91d066d657de8d6f38"), "text" : "RT @RevRunWisdom: The bravest thing that men do is love women #love", "created_at" : "Thu Sep 02 18:11:24 +0000 2010", … "user" : { "friends_count" : 0, "profile_sidebar_fill_color" : "252429", "screen_name" : "RevRunWisdom", "name" : "Rev Run", }, …
  • 77. Word Count: Map Funktion // Map Funktion mit Bereinigung der Daten map = function() { this.text.split(' ').forEach(function(word) { // Entfernen von Whitespace word = word.replace(/s/g, ""); // Entfernen alle Non-Word-Characters word = word.replace(/W/gm,""); // Finally emit the cleaned up word if(word != "") { emit(word, 1) } }); };
  • 78. Word Count: Reduce Funktion // Reduce Funktion reduce = function(key, values) { return values.length; };
  • 79. Word Count: Aufruf // Anzeigen des Ergebnisses in der Konsole > db.tweets.mapReduce(map, reduce, { out : { inline : 1 } } ); // Speichern des Ergebnisses in einer Collection > db.tweets.mapReduce(map, reduce, { out : "tweets_word_count"} ); { "result" : "tweets_word_count", "timeMillis" : 19026, "counts" : { "input" : 53641, "emit" : 559217, "reduce" : 102057, "output" : 131003 }, "ok" : 1, }
  • 80. Word Count: Ergebnis // Ausgeben der 10 häufigsten Wörter in Tweets > db.tweets_word_count.find().sort({"value" : -1}).limit(10) { { { { { { { { { { "_id" "_id" "_id" "_id" "_id" "_id" "_id" "_id" "_id" "_id" : : : : : : : : : : "Miley", "value" : 31 } "mil", "value" : 31 } "andthenihitmydougie", "value" : 30 } "programa", "value" : 30 } "Live", "value" : 29 } "Super", "value" : 29 } "cabelo", "value" : 29 } "listen", "value" : 29 } "Call", "value" : 28 } "DA", "value" : 28 }
  • 82. Indexe in MongoDB sind B-Trees
  • 83. Abfragen, Einfügen und Löschen: O(log(n))
  • 84. Fehlende oder nicht optimale Indexe sind das häufigste vermeidbare MongoDB Performance-Problem
  • 85. Wie lege ich Indexe an? // Anlegen eines Index, wenn er noch nicht existiert > db.recipes.createIndex({ main_ingredient: 1 }) // Der Client merkt sich den Index und wirft keinen Fehler > db.recipes.ensureIndex({ main_ingredient: 1 }) * 1 für aufsteigend, -1 für absteigend
  • 86. Was kann indexiert werden? // Mehrere Felder (Compound Key Indexes) > db.recipes.ensureIndex({ main_ingredient: 1, calories: -1 }) // Arrays mit Werten (Multikey Indexes) { name: 'Chicken Noodle Soup’, ingredients : ['chicken', 'noodles'] } > db.recipes.ensureIndex({ ingredients: 1 })
  • 87. Was kann indexiert werden? // Subdokumente { name : 'Apple Pie', contributor: { name: 'Joe American', id: 'joea123' } } db.recipes.ensureIndex({ 'contributor.id': 1 }) db.recipes.ensureIndex({ 'contributor': 1 })
  • 88. Wie verwalte ich Indexe? // Auflisten aller Indexe einer Collection > db.recipes.getIndexes() > db.recipes.getIndexKeys() // Löschen eines Index > db.recipes.dropIndex({ ingredients: 1 }) // Löschen und Neuerzeugung aller Indexe db.recipes.reIndex() // Defaultindex auf _id
  • 89. Weitere Optionen • Unique Indexe – Nur eindeutige Werte erlaubt • Sparse Indexe – Für Felder, die nicht in allen Dokumenten vorkommen • Geospatial Indexe – Zur Modellierung von Geoinformationen • TTL Collections – Verfallen nach x Sekunden
  • 90. Unique Indexe // Der Name eines Rezepts muss eindeutig sein > db.recipes.ensureIndex( { name: 1 }, { unique: true } ) // Erzwingen eines Index auf einer Collection mit nicht eindeutigen // Namen – Die Duplikate werden gelöscht > db.recipes.ensureIndex( { name: 1 }, { unique: true, dropDups: true } ) * dropDups bitte mit sehr viel Vorsicht anwenden!
  • 91. Sparse Indexe // Nur Dokumente mit dem Feld calories werden indexiert > db.recipes.ensureIndex( { calories: -1 }, { sparse: true } ) // Kombination mit einem Unique Index möglich > db.recipes.ensureIndex( { name: 1 , calories: -1 }, { unique: true, sparse: true } ) * Fehlende Felder werden im Index als null gespeichert
  • 92. Geospatial Indexe // Hinzufügen von Längen- und Breitengraden { name: ‚codecentric Frankfurt’, loc: [ 50.11678, 8.67206] } // Indexierung der Koordinaten > db.locations.ensureIndex( { loc : '2d' } ) // Abfrage nach Orten in der Nähe von codecentric Frankfurt > db.locations.find({ loc: { $near: [ 50.1, 8.7 ] } })
  • 93. TTL Collections // Die Dokumente müssen ein Datum des Typs BSON UTC haben { ' submitted_date ' : ISODate('2012-10-12T05:24:07.211Z'), … } // Dokumente werden automatisch nach 'expireAfterSeconds' // Sekunden gelöscht > db.recipes.ensureIndex( { submitted_date: 1 }, { expireAfterSeconds: 3600 } )
  • 94. Limitierungen von Indexen • Collections können nicht mehr als 64 Indexe haben. • Indexschlüssel können nicht größer als 1024 Byte sein. • Der Name eines Index inklusive Namespace muss kleiner als 128 Zeichen sein. • Abfragen können nur einen Index verwenden – Ausnahme: Abfragen mit $or • Indexe verbrauchen Speichern und verlangsamen das Schreiben von Daten
  • 96. Vorgehensweise 1. Langsame Abfragen identifizieren 2. Mittels explain() mehr über die langsame Abfrage herausfinden 3. Anlegen der Indexe auf den abgefragten Feldern 4. Optimierung der Abfragen anhand der verwendeten Indexe
  • 97. 1. Langsame Abfragen identifizieren > db.setProfilingLevel( n , slowms=100ms ) n=0: Profiler abgeschaltet n=1: Protokollieren aller Abfragen langsamer als slowms n=2: Protokollieren aller Operationen > db.system.profile.find() * Die Collection profile ist eine Capped Collection und hat daher eine feste Anzahl von Einträgen
  • 98. 2. Benutzung von explain() > db.recipes.find( { calories: { $lt : 40 } } ).explain( ) { "cursor" : "BasicCursor" , "n" : 42, "nscannedObjects” : 53641 "nscanned" : 53641, ... "millis" : 252, ... } * Keine Verwendung von Plänen aus dem Cache und erneuten Ausführungen
  • 99. 2. Metriken des Executionplans I • Cursor – Der Typ des Cursors. BasicCursor bedeutet, dass kein Index benutzt wurde • n – Die Anzahl der passenden Dokumente • nscannedObjects – Die Anzahl der gescannten Dokumente • nscanned – Die Anzahl der untersuchten Einträge (Indexeinträge oder Dokumente)
  • 100. 2. Metriken des Executionplans II • millis – Ausführungszeit der Abfrage • Komplette Referenz unter – http://docs.mongodb.org/manual/reference/explain Das Verhältnis der gescannten zu den gefundenen Dokumenten sollte möglichst nahe an 1 sein!
  • 101. 3. Anlegen der Indexe auf den abgefragten Feldern
  • 102. 4. Optimierung der Abfragen anhand der verwendeten Indexe // Bei folgendem Index… > db.collection.ensureIndex({ a:1, b:1 , c:1, d:1 }) // // > > … können die folgenden Sortieroperationen und Abfragen den Index benutzen db.collection.find( ).sort({ a:1 }) db.collection.find( ).sort({ a:1, b:1 }) > db.collection.find({ a:4 }).sort({ a:1, b:1 }) > db.collection.find({ b:5 }).sort({ a:1, b:1 })
  • 103. 4. Optimierung der Abfragen anhand der verwendeten Indexe // Bei folgendem Index… > db.collection.ensureIndex({ a:1, b:1, c:1, d:1 }) // … können diese Abfragen ihn nicht verwenden > db.collection.find( ).sort({ b: 1 }) > db.collection.find({ b: 5 }).sort({ b: 1 })
  • 104. 4. Optimierung der Abfragen anhand der verwendeten Indexe // Bei folgendem Index… > db.recipes.ensureIndex({ main_ingredient: 1, name: 1 }) // … verwendet diese Abfrage nur Felder des Index > db.recipes.find( { main_ingredient: 'chicken’ }, { _id: 0, name: 1 } ) // Das Feld indexOnly bei explain() zeigt dies an > db.recipes.find( { main_ingredient: 'chicken' }, { _id: 0, name: 1 } ).explain() { "indexOnly": true, }
  • 105. Index manuell angeben // MongoDB mitteilen, welcher Index verwendet werden soll > db.recipes.find({ calories: { $lt: 1000 } } ).hint({ _id: 1 }) // Die Verwendung von Indexen ausschalten (z.B. zur Performance// messung > db.recipes.find( { calories: { $lt: 1000 } } ).hint({ $natural: 1 })
  • 107. Mehrere Index verwenden // MongoDB kann nur einen Index pro Abfrage verwenden > db.collection.ensureIndex({ a: 1 }) > db.collection.ensureIndex({ b: 1 }) // Nur einer der beiden obigen Indexe wird verwendet > db.collection.find({ a: 3, b: 4 })
  • 108. Zusammengesetzte Indexe // Zusammengesetzte Indexe sind im Allgemeinen sehr effektiv > db.collection.ensureIndex({ a: 1, b: 1, c: 1 }) // Aber nur wenn die Abfrage ein Präfix des Indexes ist… // Diese Abfrage kann den Index nicht effektiv verwenden db.collection.find({ c: 2 }) // …diese Abfrage hingegen schon db.collection.find({ a: 3, b: 5 })
  • 109. Indexe mit geringer Selektivität // Folgendes Feld hat nur sehr wenige eindeutige Werte > db.collection.distinct('status’) [ 'new', 'processed' ] // Ein Index auf diesem Feld bringt nur sehr wenig > db.collection.ensureIndex({ status: 1 }) > db.collection.find({ status: 'new' }) // Besser ist ein zusammengesetzter Index zusammen mit einem // anderen Feld > db.collection.ensureIndex({ status: 1, created_at: -1 }) > db.collection.find( { status: 'new' } ).sort({ created_at: -1 })
  • 110. Reguläre Ausdrücke & Indexe > db.users.ensureIndex({ username: 1 }) // Abfragen mit regulären Ausdrücken, die linksgebunden sind // können den Index verwenden > db.users.find({ username: /^joe smith/ }) // Generische Abfragen mit regulären Ausdrücken hingegen nicht… > db.users.find({username: /smith/ }) // Ebenso nicht schreibungsunabhängige Abfragen… > db.users.find({ username: /Joe/i })
  • 111. Negation // Bei Negationen können Indexe nicht verwendet werden > db.things.ensureIndex({ x: 1 }) // z.B. bei Abfragen mit not equal > db.things.find({ x: { $ne: 3 } }) // …oder Abfragen mit not in > db.things.find({ x: { $nin: [2, 3, 4 ] } }) // …oder Abfragen mit dem $not Operator > db.people.find({ name: { $not: 'John Doe' } })
  • 112. Konsistenz beim Schreiben und Lesen von Daten
  • 115. Write Concern - Schreibmodi • Bestätigung durch das Netzwerk • Bestätigung durch MongoDB • Bestätigung durch das Journal • Bestätigung durch Secondaries • Bestätigung durch Tagging
  • 116. Bestätigung durch das Netzwerk „Fire and forget“
  • 118. Bestätigung durch das Journal Wait for Journal Sync
  • 120. Tagging beim Schreiben • Verfügbar seit Version 2.0 • Ermöglicht stärkere Kontrolle woher Daten gelesen und wohin geschrieben werden • Jeder Knoten kann mehrere Tags haben – tags: {dc: "ny"} – tags: {dc: "ny", subnet: „192.168", rack: „row3rk7"} • Erlaubt das Anlegen für Regeln für das Write Concern pro Replikaset • Anpassung der Regeln ohne Codeänderung
  • 121. Beispiel für Tagging { _id : "mySet", members : [ {_id : 0, host : "A", tags : {"dc": "ny"}}, {_id : 1, host : "B", tags : {"dc": "ny"}}, {_id : 2, host : "C", tags : {"dc": "sf"}}, {_id : 3, host : "D", tags : {"dc": "sf"}}, {_id : 4, host : "E", tags : {"dc": "cloud"}}], settings : { getLastErrorModes : { allDCs : {"dc" : 3}, someDCs : {"dc" : 2}} } } > db.blogs.insert({...}) > db.runCommand({getLastError : 1, w : "someDCs"})
  • 122. Bestätigung durch alle Datenzentren Wait for Replication (Tagging)
  • 123. Setzen des Write Concerns // Wait for network acknowledgement > db.runCommand( { getLastError: 1, w: 0 } ) // Wait for error (Default) > db.runCommand( { getLastError: 1, w: 1 } ) // Wait for journal sync > db.runCommand( { getLastError: 1, w: 1, j: "true" } ) // Wait for replication > db.runCommand( { getLastError: 1, w: “majority" } ) // Mehrheit > db.runCommand( { getLastError: 1, w: 3 } ) // # der Secondaries
  • 124. Modi zum Lesen von Daten (Seit Version 2.2) • Nur Primary (primary) • Primary bevorzugt (primaryPreferred) • Nur Secondaries (secondary) • Secondaries bevorzugt (secondaryPreferred) • Nähester Knoten (Nearest) Falls mehr als ein Knoten möglich ist, wird immer der näheste Knoten zum Lesen der Daten verwendet. (Alle Modi außer Primary)
  • 130. Tagging beim Lesen • Ermöglicht eine individuelle Kontrolle woher Daten gelesen werden – z.B. { "disk": "ssd", "use": "reporting" } • Lässt sich mit den Standard-Lese-Modi kombinieren – Außer dem Modus „Nur Primary“
  • 131. Setzen der Read Preference // Nur Primary > cursor.setReadPref( “primary" ) // Primary bevorzugt > cursor.setReadPref( “primaryPreferred" ) …. // Nur Secondaries mit Tagging > cursor.setReadPref( “secondary“, [ rack : 2 ] ) Aufruf der Methode auf dem Cursor muss vor dem Lesen der Dokumente erfolgen
  • 132. Java API & Frameworks
  • 135. MongoDB Treiber • Ein Wire Protokoll für alle Programmiersprachen • Eine Implementierung des Treibers pro Sprache • Hauptaufgaben: – Konvertierung der sprachspezifischen Datenstrukturen nach BSON – Generierung der ObjectId für das Feld _id
  • 136. MongoDB Java Treiber • Ein JAR ohne weitere Abhängigkeiten: <dependency> <groupId>org.mongodb</groupId> <artifactId>mongo-java-driver</artifactId> <version>2.11.3</version> </dependency> Verfügbar auf Github: https://github.com/mongodb/mongo-java-driver
  • 137. Verbindungsaufbau import com.mongodb.MongoClient; // Default: localhost:27017 mongo = new MongoClient(); // Replica set mongo = new MongoClient(Arrays.asList( new ServerAddress("replicant01", 10001), new ServerAddress("replicant02", 10002), new ServerAddress("replicant03", 10003) )); // Sharding: mongos server mongo = new MongoClient("mongos01", 4711);
  • 138. Zugriff auf Datenbank und Collection import com.mongodb.DB; import com.mongodb.DBCollection; DB db = mongo.getDB("test"); DBCollection collection = db.getCollection("foo");
  • 139. Dokument einfügen import com.mongodb.BasicDBObject; import com.mongodb.DBObject; // insert document DBObject doc = new BasicDBObject(); doc.put("date", new Date()); doc.put("i", 42); collection.insert(doc);
  • 140. Dokumente abfragen import com.mongodb.DBCursor; DBCursor cursor; cursor = collection.find(); // all documents // documents w/ {i: 42} cursor = collection.find( new BasicDBObject("i", 42) ); document = cursor.next(); ...
  • 141. Beispiel: Bestellung > db.order.find( {"items.quantity": ? } )
  • 142. Beispiel: Bestellung I DB db = mongo.getDB("test"); DBCollection collection = db.getCollection("order"); DBObject order; List<DBObject> items = new ArrayList<DBObject>(); DBObject item; // order order = new BasicDBObject(); order.put("date", new Date()); order.put("custInfo" , „Sheldon Cooper"); // items item = new BasicDBObject(); item.put("quantity", 1); item.put("price", 47.11); item.put("desc", "Item #1"); items.add(item); item = new BasicDBObject(); item.put("quantity", 2); item.put("price", 42.0); item.put("desc", "Item #2"); items.add(item); order.put("items", items); collection.insert(order);
  • 143. Beispiel: Bestellung II DB db = mongo.getDB("test"); DBCollection collection = db.getCollection("order"); DBObject query; DBObject document; DBCursor cursor; query = new BasicDBObject("items.quantity", 2); cursor = collection.find(query); while ( cursor.hasNext() ) { document = cursor.next(); println(document); }
  • 144. Jongo
  • 145. Kurzüberblick über Jongo Entwickler Lizenz Dokumentation Hauptmerkmale Benoît Guérout, Yves Amsellem Apache License, Version 2.0 http://jongo.org/ • Object/Document Mapping • Eigene Query API
  • 146. Query in Java as in Mongo Shell
  • 147. Jongo: Object Mapping public class Order { private ObjectId id; private Date date; @JsonProperty("custInfo") private String customerInfo; List<Item> items; … } public class Item { private int quantity; private double price; @JsonProperty("desc") private String description; … }
  • 148. Jongo: Abfragen // Java driver API MongoClient mc = new MongoClient(); DB db = mc.getDB("odm_jongo"); // Jongo API entry point Jongo jongo = new Jongo(db); MongoCollection orders = jongo.getCollection("order"); // no DAO needed Iterable<Order> result = orders.find("{"items.quantity": #}", 2).as(Order.class); // supports projection Iterable<X> result = orders.find().fields("{_id:0, date:1, custInfo:1}").as(X.class);
  • 150. Kurzüberblick über Morphia Entwickler Lizenz Dokumentation Scott Hernandez, James Green Apache License, Version 2.0 https://github.com/jmkgreen/morph ia/wiki/Overview Hauptmerkmale • Object/Document Mapping • Eigene Query API • Unterstützung für DAO‘s
  • 151. Morphia: Object Mapping public class Order { @Id private ObjectId id; private Date date; @Property("custInfo") private String customerInfo; @Embedded List<Item> items; ... } public class Item { private int quantity; private double price; @Property("desc") private String description; ... }
  • 152. Morphia: Abfragen public class OrderDao extends BasicDAO<Order, ObjectId> { List<Order> findByItemsQuantity(int quantity) { return find( createQuery().filter("items.quantity", quantity)) .asList(); } List<Order> findByItemsPriceGreaterThan(double price) { return find( createQuery().field("items.price").greaterThan(price) ) .asList(); } … }
  • 153. Morphia: Eigene Syntax für Abfragen Morphia Mongo Query = !=, <> >, <, >=,<= in, nin elem … $eq $neq $gt, $lt, $gte, $lte $in, $nin $elemMatch ….
  • 155. Kurzüberblick über Spring Data MongoDB Hersteller Lizenz Dokumentation VMware / SpringSource Apache License, Version 2.0 http://www.springsource.org/spring -data/mongodb Hauptmerkmale • Repository Support • Object/Document Mapping • Templating
  • 156. Spring Data CrudRepository Spring Data JPA PagingAndSortingRepository Spring Data Neo4j MongoReposito ry GraphRepos itory MongoT em plate JpaRepository Spring Data MongoDB Neo4 jTemplate Em bedded JPA JDBC RDBMS Spring Data … RES T Mongo Java Driver Mongo DB Neo4j … Einheitliche Architektur für relationale Datenbanken sowie für unterstützte NoSQL-Stores
  • 157. Spring Data MongoDB • Repository Support – Abfragen werden aus den Methodensignaturen erstellt – Annotationen für Abfragen • Object-Document-Mapping – Annotationen: @Document, @Field, @Index, … – Klassen werden auf Collections gemappt, Javaobjekte auf Dokumente • Templating – – – – Abstraktion der Ressourcen Konfigurierbarkeit der Verbindungen zu MongoDB Abdeckung des Lebenszyklus einer Collection Unterstützung für Map/Reduce & Aggregation Framework
  • 158. Spring Data MongoDB: Konfiguration <!-- Connection to MongoDB server --> <mongo:db-factory host="localhost" port="27017" dbname="test" /> <!-- MongoDB Template --> <bean id="mongoTemplate, class="org.springframework.data.mongodb.core.MongoTemplate"> <constructor-arg name="mongoDbFactory" ref="mongoDbFactory"/> </bean> <!-- Package w/ automagic repositories --> <mongo:repositories base-package="mongodb" />
  • 159. Spring Data MongoDB: Template <mongo:mongo host="${mongo.host}" port="${mongo.port}"> <mongo:options connections-per-host="${mongo.connectionsPerHost}„ threads-allowed-to-block-for-connection multiplier="${mongo.threadsAllowedToBlockForConnectionMultiplier}„ connect-timeout="${mongo.connectTimeout}„ max-wait-time="${mongo.maxWaitTime}„ auto-connect-retry="${mongo.autoConnectRetry}„ socket-keep-alive="${mongo.socketKeepAlive}„ socket-timeout="${mongo.socketTimeout}„ slave-ok="${mongo.slaveOk}„ write-number="1„ write-timeout="0„ write-fsync="true"/> </mongo:mongo> <mongo:db-factory dbname= "test" mongo-ref="mongo"/>
  • 160. Spring Data MongoDB: Object Mapping public class Order { @Id private String id; private Date date; @Field("custInfo") private String customerInfo; List<Item> items; ... } public class Item { private int quantity; private double price; @Field("desc") private String description; ... }
  • 161. Spring Data MongoDB: Repository Support public interface OrderRepository extends MongoRepository<Order, String> { List<Order> findByItemsQuantity(int quantity); List<Order> findByItemsPriceGreaterThan(double price); }
  • 162. Spring Data MongoDB: Zusätzliche Unterstützung für… • Map/Reduce & das Aggregation Framework • Das Management von Indexen • Grosse Dateien mittels GridFS • Geoinformatische Indexe und Abfragen • Optimistisches Locking
  • 164. Kurzüberblick über Hibernate OGM MongoDB Hersteller Lizenz Dokumentation JBoss / Redhat GNU LGPL, Version 2.1 http://www.hibernate.org/subproject s/ogm.html Hauptmerkmale • JPA API (Teilweise) • JPQL Query Language
  • 165. Hibernate OGM • Implementiert ein Subset der JPA API • JP-QL Anfragen werden in native Datenbankabfragen übersetzt • Unterstützt Infinispan, EhCache, MongoDB
  • 167. Hibernate OGM MongoDB: Konfiguration <persistence version="2.0" …> <persistence-unit name="primary"> <provider>org.hibernate.ogm.jpa.HibernateOgmPersistence</provider> <class>hibernate.Order</class> <class>hibernate.Item</class> <properties> <property name="hibernate.ogm.datastore.provider" value="org.hibernate.ogm.datastore.mongodb.impl.MongoDBDatastorePr ovider"/> <property name="hibernate.ogm.mongodb.database" value=„odm"/> <property name="hibernate.ogm.mongodb.host" value=„localhost"/> <property name="hibernate.ogm.mongodb.port" value=„27017"/> </properties> </persistence-unit> </persistence>
  • 168. Hibernate OGM MongoDB: Object Mapping @Entity @NamedQuery( name="byItemsQuantity", query = "SELECT o FROM Order o JOIN o.items i WHERE i.quantity = :quantity" ) public class Order { @GeneratedValue(generator = "uuid") @GenericGenerator(name = "uuid", strategy = "uuid2") @Id private String id; private Date date; @Column(name = "custInfo") private String customerInfo; @ElementCollection private List<Item> items; @Embeddable public class Item { private int quantity; private double price; @Column(name="desc") private String description; ...
  • 169. Hibernate OGM MongoDB: Aktueller Status • Frühes Beta-Stadium • Aktuell nur Speichern / Mergen / Löschen von Daten möglich • Noch keine Unterstützung für Abfragen • Benutzt eine relationale API
  • 170. Not yet ready for prime time…
  • 172. Was sollte ich einsetzen? - „Ready for production“ JPA Hibernate OGM Spring Data MongoDB - Aktive Community - Ältestes Framework - Nicht so mächtig wie Spring - Frühes Betastadium - Diskrepanz in API Morphia Der „bessere“ Treiber Jongo JDBC MongoDB Java Driver - „Ready for production“ - Von MongoDB Inc. unterstützt MongoDB
  • 175. So Long, and Thanks for All the Fish!