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 Per...
Agenda
•

Buzzword Bingo

•

Überblick über MongoDB

•

Datenmanipulation

•

Indexing

• Konsistenz beim Schreiben und Le...
Buzzword Bingo
NoSQL
Klassifizierung von NoSQL
Key-Value Stores
K

V

K

V

K

V

K

1

V

K

Column Stores

V

Graph Databases

1

1
1
1

1
1
...
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
Storag...
Das Problem
mit der
Verteilung
Das CAP Theorem
Availability
Jede Anfrage
bekommt eine
Antwort

Consistency
Alle Knoten
haben
jederzeit die
gleichen
Infor...
Überblick über NoSQL Systeme

Availability
Jeder Client
kann immer
schreiben und
lesen

C

onsistency

Alle Knoten
haben
j...
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

Schwach...
Überblick über MongoDB
MongoDB ist eine …
•

Dokumenten-basierte

•

Open Source

•

Performante

•

Flexible

•

Skalierbare

•

Hochverfügbare
...
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 u...
Performance

Datenlokalität

In-Memory
Caching

In-Place
Updates
Flexibles Schema
MongoDB

RDBMS
{

_id :
ObjectId("4c4ba5e5e8aabf3"),
employee_name: "Dunham, Justin",
department : "Marke...
Skalierbarkeit
Auto-Sharding

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

• Automatische Replikation und Failover
• Unterstützung für mehrere Datenzentren
• Ausgelegt auf möglic...
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 ...
NoSQL Trends
Google Search

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

...
Datenmanipulation
Terminologie
RDBMS
Tabelle / View
Zeile
Index
Join
Fremdschlüssel
Partition

MongoDB
➜
➜
➜
➜

Collection
Dokument
Index
Ei...
Let’s have a look…
Anlegen einer Datenbank
// Anzeigen aller Datenbanken
> show dbs
digg 0.078125GB
enron 1.49951171875GB
// Wechsel in eine ...
Anlegen einer Collection I
// Anzeigen aller Collections
> show collections
// Einfügen eines Benutzers
> db.user.insert(
...
Anlegen einer Collection II
// Anzeigen aller Collections
> show collections
system.indexes
user
// Anzeigen aller Datenba...
Lesen aus einer Collection
// Anzeigen des ersten Dokuments
> db.user.findOne()
{
"_id" : ObjectId("516684a32f391f3c2fcb80...
Filtern von Dokumenten
// Filtern von bestimmten Dokumenten
> db.user.find( { name : ”Penny” } )
{
"_id" : ObjectId("5166a...
_id
•

_id ist der primäre Schlüssel in MongoDB

•

Index auf _id wird automatisch erzeugt

•

Wenn nicht anders angegeben...
ObjectId
•

Eine ObjectId ist ein spezieller 12 Byte
Wert

•

Ihre Einzigartigkeit über den gesamten
Cluster ist durch die...
Cursor
// Benutzen eines Cursors für die Dokumente
> var myCursor = db.user.find( )
// Nächstes Dokument holen und Mail an...
Logische Verknüpfungen
// Oder-Verknüpfung
> db.user.find(
{$or : [ { name : “Sheldon“ },
{ mail : amy@bigbang.com }
]
})
...
Ergebnismengen anpassen
// Sortieren von Dokumenten
> db.user.find().sort( { name : 1 } ) // Aufsteigend
> db.user.find()....
Update von Dokumenten I
// Update der Mail-Adresse (So bitte nicht!)
> db.user.update( { name : “Sheldon“ },
{ mail : “she...
Löschen von Dokumenten
// Löschen des Dokuments
> db.user.remove(
{ mail : “sheldon@howimetyourmother.com“ }
)
// Löschen ...
Update von Dokumenten II
// Update der Mail-Adresse (Jetzt aber richtig!)
> db.user.update( { name : “Sheldon“ },
{ $set :...
Hinzufügen zu Arrays
// Hinzufügen eines Arrays
> db.user.update( {name : “Sheldon“ },
{ $set : {enemies :
[ { name : “Wil...
Löschen aus Arrays
// Löschen eines Wertes aus dem Array
> db.user.update( { name : “Sheldon“ },
{$pull : {enemies :
{name...
Einfügen eines Subdokuments
// Hinzufügen eines Subdokuments
> db.user.update( { name : “Sheldon“}, {
$set : { mother :{ n...
Abfragen auf Subdokumenten
// Abfrage des Namens der Mutter
> db.user.find( { name : “Sheldon“},
{“mother.name“ : 1 } )
{
...
Übersicht über alle UpdateOperatoren
Für Felder:
$inc
$rename
$set
$unset
Bitweise:
$bit
Isolation:
$isolated

Für Arrays:...
Dokumentation

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

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

Update
...
Das Aggregation Framework
•

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

•

Framework von Meth...
Aggregation Pipeline
Pipeline
Operator
Pipeline
Operator
Pipeline
Operator

{
document
}

Ergebnis
{
sum: 337
avg: 24,53
m...
Aggregation Pipeline
•

Verarbeitet einen Strom von Dokumenten
– Eingabe ist eine Collection
– Ausgabe ist ein Ergebnisdok...
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
...
Aggregation Framework I
// Collection mit Tweets
{
"_id" : ObjectId("4fb9fb91d066d657de8d6f39"),
"text" : "I can't wait fo...
Aggregation Framework II
// Finde die Top-3-Twitterer nach Followern
> db.tweets.aggregate(
{ $project : {name : "$user.na...
Aggregation Framework III
// Finde die Top-3-Links aus Tweets
> db.tweets.aggregate(
{ $project : {_id: 0, inhalt_des_twee...
Was ist Map/Reduce?
•

Programmiermodel aus der funktionalen
Welt

•

Framework zur
– parallelen Verarbeitung
– von großen...
Map/Reduce mit MongoDB
MongoDB

map()

Daten

group(k)

emit(k,v)
Shard 1

• Iteriert über
alle
Dokumente

sort(k)

Shard ...
Word Count: Problemstellung
INPUT
{
MongoDB
uses
MapReduce
}

{
There is a
map phase
}

{
There is a
reduce
phase
}

MAPPE...
Word Count: Tweets
// Beispiel: Twitter-Datenbank mit Tweets
> db.tweets.findOne()
{
"_id" : ObjectId("4fb9fb91d066d657de8...
Word Count: Map Funktion
// Map Funktion mit Bereinigung der Daten
map = function() {
this.text.split(' ').forEach(functio...
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 } } ...
Word Count: Ergebnis
// Ausgeben der 10 häufigsten Wörter in Tweets
> db.tweets_word_count.find().sort({"value" : -1}).lim...
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...
Was kann indexiert werden?
// Mehrere Felder (Compound Key Indexes)
> db.recipes.ensureIndex({
main_ingredient: 1,
calorie...
Was kann indexiert werden?
// Subdokumente
{
name : 'Apple Pie',
contributor: {
name: 'Joe American',
id: 'joea123'
}
}
db...
Wie verwalte ich Indexe?
// Auflisten aller Indexe einer Collection
> db.recipes.getIndexes()
> db.recipes.getIndexKeys()
...
Weitere Optionen
•

Unique Indexe
– Nur eindeutige Werte erlaubt

•

Sparse Indexe
– Für Felder, die nicht in allen Dokume...
Unique Indexe
// Der Name eines Rezepts muss eindeutig sein
> db.recipes.ensureIndex( { name: 1 }, { unique: true } )

// ...
Sparse Indexe
// Nur Dokumente mit dem Feld calories werden indexiert
> db.recipes.ensureIndex(
{ calories: -1 },
{ sparse...
Geospatial Indexe
// Hinzufügen von Längen- und Breitengraden
{
name: ‚codecentric Frankfurt’,
loc: [ 50.11678, 8.67206]
}...
TTL Collections
// Die Dokumente müssen ein Datum des Typs BSON UTC haben
{ ' submitted_date ' : ISODate('2012-10-12T05:24...
Limitierungen von Indexen
•

Collections können nicht mehr als 64 Indexe haben.

•

Indexschlüssel können nicht größer als...
Optimierung von Indexen
Vorgehensweise
1. Langsame Abfragen identifizieren
2. Mittels explain() mehr über die

langsame Abfrage herausfinden
3. An...
1. Langsame Abfragen
identifizieren
> db.setProfilingLevel( n , slowms=100ms )

n=0: Profiler abgeschaltet
n=1: Protokolli...
2. Benutzung von explain()
> db.recipes.find( { calories:
{ $lt : 40 } }
).explain( )
{
"cursor" : "BasicCursor" ,
"n" : 4...
2. Metriken des Executionplans I
• Cursor
– Der Typ des Cursors. BasicCursor bedeutet, dass

kein Index benutzt wurde

• n...
2. Metriken des Executionplans II
• millis
– Ausführungszeit der Abfrage

• Komplette Referenz unter
– http://docs.mongodb...
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 ,...
4. Optimierung der Abfragen
anhand der verwendeten Indexe
// Bei folgendem Index…
> db.collection.ensureIndex({ a:1, b:1, ...
4. Optimierung der Abfragen
anhand der verwendeten Indexe
// Bei folgendem Index…
> db.recipes.ensureIndex({ main_ingredie...
Index manuell angeben
// MongoDB mitteilen, welcher Index verwendet werden soll
> db.recipes.find({
calories: { $lt: 1000 ...
Häufige Stolperfallen
bei Indexen
Mehrere Index verwenden
// MongoDB kann nur einen Index pro Abfrage verwenden
> db.collection.ensureIndex({ a: 1 })
> db.c...
Zusammengesetzte Indexe
// Zusammengesetzte Indexe sind im Allgemeinen sehr effektiv
> db.collection.ensureIndex({ a: 1, b...
Indexe mit geringer
Selektivität
// Folgendes Feld hat nur sehr wenige eindeutige Werte
> db.collection.distinct('status’)...
Reguläre Ausdrücke & Indexe
> db.users.ensureIndex({ username: 1 })

// Abfragen mit regulären Ausdrücken, die linksgebund...
Negation
// Bei Negationen können Indexe nicht verwendet werden
> db.things.ensureIndex({ x: 1 })
// z.B. bei Abfragen mit...
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 Jour...
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 gesch...
Beispiel für Tagging
{
_id : "mySet",
members : [
{_id : 0, host : "A", tags : {"dc": "ny"}},
{_id : 1, host : "B", tags :...
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 err...
Modi zum Lesen von Daten
(Seit Version 2.2)
•

Nur Primary

(primary)

•

Primary bevorzugt

(primaryPreferred)

•

Nur Se...
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": "re...
Setzen der Read Preference
// Nur Primary
> cursor.setReadPref( “primary" )
// Primary bevorzugt
> cursor.setReadPref( “pr...
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

•

H...
MongoDB Java Treiber
•

Ein JAR ohne weitere Abhängigkeiten:
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo...
Verbindungsaufbau
import com.mongodb.MongoClient;
// Default: localhost:27017
mongo = new MongoClient();
// Replica set
mo...
Zugriff auf Datenbank und
Collection
import com.mongodb.DB;
import com.mongodb.DBCollection;
DB db = mongo.getDB("test");
...
Dokument einfügen
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
// insert document
DBObject doc = new Bas...
Dokumente abfragen
import com.mongodb.DBCursor;
DBCursor cursor;
cursor = collection.find(); // all documents
// documents...
Beispiel: Bestellung

> db.order.find( {"items.quantity": ? } )
Beispiel: Bestellung I
DB db = mongo.getDB("test");
DBCollection collection = db.getCollection("order");
DBObject order;
L...
Beispiel: Bestellung II
DB db = mongo.getDB("test");
DBCollection collection = db.getCollection("order");
DBObject query;
...
Jongo
Kurzüberblick über Jongo
Entwickler
Lizenz
Dokumentation
Hauptmerkmale

Benoît Guérout, Yves Amsellem
Apache License, Vers...
Query in Java as in Mongo Shell
Jongo: Object Mapping
public class Order {
private ObjectId id;
private Date date;
@JsonProperty("custInfo") private Strin...
Jongo: Abfragen
// Java driver API
MongoClient mc = new MongoClient();
DB db = mc.getDB("odm_jongo");
// Jongo API entry p...
Morphia
Kurzüberblick über Morphia

Entwickler
Lizenz
Dokumentation

Scott Hernandez, James Green
Apache License, Version 2.0
http...
Morphia: Object Mapping
public class Order {
@Id private ObjectId id;
private Date date;
@Property("custInfo") private Str...
Morphia: Abfragen
public class OrderDao extends BasicDAO<Order, ObjectId> {
List<Order> findByItemsQuantity(int quantity) ...
Morphia: Eigene Syntax für
Abfragen
Morphia

Mongo Query

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

$eq
$neq
$gt, $lt, $gte, $l...
Spring Data MongoDB
Kurzüberblick über
Spring Data MongoDB
Hersteller
Lizenz
Dokumentation

VMware / SpringSource
Apache License, Version 2.0
...
Spring Data
CrudRepository
Spring Data
JPA

PagingAndSortingRepository
Spring Data
Neo4j

MongoReposito
ry

GraphRepos ito...
Spring Data MongoDB
•

Repository Support
– Abfragen werden aus den Methodensignaturen erstellt
– Annotationen für Abfrage...
Spring Data MongoDB:
Konfiguration
<!-- Connection to MongoDB server -->
<mongo:db-factory host="localhost" port="27017" d...
Spring Data MongoDB:
Template
<mongo:mongo host="${mongo.host}" port="${mongo.port}">
<mongo:options
connections-per-host=...
Spring Data MongoDB:
Object Mapping
public class Order {
@Id private String id;
private Date date;
@Field("custInfo") priv...
Spring Data MongoDB:
Repository Support
public interface OrderRepository extends
MongoRepository<Order, String> {
List<Ord...
Spring Data MongoDB:
Zusätzliche Unterstützung für…
•

Map/Reduce & das Aggregation Framework

•

Das Management von Index...
Hibernate OGM
Kurzüberblick über
Hibernate OGM MongoDB
Hersteller
Lizenz
Dokumentation

JBoss / Redhat
GNU LGPL, Version 2.1
http://www....
Hibernate OGM
• Implementiert ein Subset der JPA API
• JP-QL Anfragen werden in native

Datenbankabfragen übersetzt
• Unte...
Architektur von
Hibernate OGM

Source:
http://docs.jboss.org/hibernate/ogm/4.0/reference/en-US/html/ogm-architecture.html#...
Hibernate OGM MongoDB:
Konfiguration
<persistence version="2.0" …>
<persistence-unit name="primary">
<provider>org.hiberna...
Hibernate OGM MongoDB:
Object Mapping
@Entity
@NamedQuery(
name="byItemsQuantity",
query = "SELECT o FROM Order o JOIN o.i...
Hibernate OGM MongoDB:
Aktueller Status
•

Frühes Beta-Stadium

• Aktuell nur Speichern / Mergen /

Löschen von Daten mögl...
Not yet ready for prime time…
Empfehlung
Was sollte ich einsetzen?
- „Ready for production“

JPA

Hibernate
OGM

Spring Data
MongoDB

- Frühes Betastadium
- Diskre...
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/
MongoDB Munich 2013

http://www.mongodb.com/events/mongodb-munich-2013/
So Long, and Thanks for All the Fish!
Upcoming SlideShare
Loading in...5
×

MongoDB für Java-Programmierer

2,287

Published on

Der Talk wurde am 25.09.2013 auf der Java User Group Frankfurt gehalten und gibt einen Überblick und Einstieg in MongoDB aus der Sicht eines Java-Programmierers.

Dabei werden folgende Themen behandelt:

- Buzzword Bingo: NoSQL, Big Data, Horizontale Skalierung, CAP-Theorem, Eventual Consistency
- Übersicht über MongoDB
- Datenmanipulation: CRUD, Aggregation Framework, Map/Reduce
- Indexing
- Konsistenz beim Schreiben und Lesen von Daten
- Java API & Frameworks

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
2,287
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
34
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

MongoDB für Java-Programmierer

  1. 1. MongoDB für Java-Programmierer Uwe Seiler uweseiler
  2. 2. About me Big Data Nerd Hadoop Trainer MongoDB Author Photography Enthusiast Travelpirate
  3. 3. About us is a bunch of… Big Data Nerds Agile Ninjas Continuous Delivery Gurus Join us! Enterprise Java Specialists Performance Geeks
  4. 4. Agenda • Buzzword Bingo • Überblick über MongoDB • Datenmanipulation • Indexing • Konsistenz beim Schreiben und Lesen von Daten • Java API & Frameworks
  5. 5. Buzzword Bingo
  6. 6. NoSQL
  7. 7. Klassifizierung von NoSQL Key-Value Stores K V K V K V K 1 V K Column Stores V Graph Databases 1 1 1 1 1 1 1 1 1 1 Document Stores _id _id _id
  8. 8. Big Data
  9. 9. Meine Lieblingsdefinition
  10. 10. Die klassische Definition • The 3 V’s of Big Data Volume Velocity •Variety
  11. 11. «Big Data» != Hadoop
  12. 12. Horizontale Skalierung
  13. 13. Vertikale Skalierung RAM CPU Storage
  14. 14. Vertikale Skalierung RAM CPU Storage
  15. 15. Vertikale Skalierung RAM CPU Storage
  16. 16. Horizontale Skalierung RAM CPU Storage
  17. 17. Horizontale Skalierung RAM CPU Storage RAM CPU Storage RAM CPU Storage RAM CPU Storage RAM CPU Storage
  18. 18. 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
  19. 19. Das Problem mit der Verteilung
  20. 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. 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
  22. 22. Das Problem mit der Konsistenz
  23. 23. ACID vs. BASE
  24. 24. ACID vs. BASE 1983 Atomicity RDBMS Consistency Isolation Durability
  25. 25. ACID vs. BASE ACID ist ein gutes Konzept, aber es ist kein in Stein gemeißeltes Gesetz!
  26. 26. ACID vs. BASE Basically Available Soft State 2008 NoSQL Eventually consistent
  27. 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
  28. 28. Überblick über MongoDB
  29. 29. MongoDB ist eine … • Dokumenten-basierte • Open Source • Performante • Flexible • Skalierbare • Hochverfügbare • Funktionsreiche …Datenbank
  30. 30. Dokumenten-basierte Datenbank • Nicht im Sinne einer Datenbank für PDFoder Worddokumente…
  31. 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
  32. 32. Performance Datenlokalität In-Memory Caching In-Place Updates
  33. 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. 34. Skalierbarkeit Auto-Sharding • Erhöhung der Kapazität wenn nötig • Ausgelegt für Commodity Hardware • Funktioniert mit Cloud-Architekturen
  35. 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
  36. 36. MongoDB Architektur
  37. 37. Reichhaltige Abfragen
  38. 38. Aggregation Framework
  39. 39. Map/Reduce MongoDB Data Map() emit(k,v) Group(k) Shard 1 Sort(k) Shard 2 … Shard n Reduce(k, values) Finalize(k, v)
  40. 40. Geoinformationen
  41. 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. 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
  43. 43. Datenmanipulation
  44. 44. Terminologie RDBMS Tabelle / View Zeile Index Join Fremdschlüssel Partition MongoDB ➜ ➜ ➜ ➜ Collection Dokument Index Eingebettetes Dokument ➜ Referenziertes Dokument ➜ Shard
  45. 45. Let’s have a look…
  46. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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)
  64. 64. 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/
  65. 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
  66. 66. Aggregation Pipeline Pipeline Operator Pipeline Operator Pipeline Operator { document } Ergebnis { sum: 337 avg: 24,53 min: 2 max : 99 }
  67. 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. 68. Aufruf > db.tweets.aggregate( { $pipeline_operator_1 { $pipeline_operator_2 { $pipeline_operator_3 { $pipeline_operator_4 ... ); }, }, }, },
  69. 69. Pipeline Operatoren // Alte Bekannte* // Neue Freunde $match $sort $limit $skip * Aus der Abfragefunktionalität $project $group $unwind
  70. 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. 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. 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. 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. 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. 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. 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. 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. 78. Word Count: Reduce Funktion // Reduce Funktion reduce = function(key, values) { return values.length; };
  79. 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. 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 }
  81. 81. Indexing
  82. 82. Indexe in MongoDB sind B-Trees
  83. 83. Abfragen, Einfügen und Löschen: O(log(n))
  84. 84. Fehlende oder nicht optimale Indexe sind das häufigste vermeidbare MongoDB Performance-Problem
  85. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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
  95. 95. Optimierung von Indexen
  96. 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. 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. 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. 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. 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. 101. 3. Anlegen der Indexe auf den abgefragten Feldern
  102. 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. 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. 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. 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 })
  106. 106. Häufige Stolperfallen bei Indexen
  107. 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. 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. 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. 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. 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. 112. Konsistenz beim Schreiben und Lesen von Daten
  113. 113. Starke Konsistenz
  114. 114. Verzögerte Konsistenz
  115. 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. 116. Bestätigung durch das Netzwerk „Fire and forget“
  117. 117. Bestätigung durch MongoDB Wait for Error
  118. 118. Bestätigung durch das Journal Wait for Journal Sync
  119. 119. Bestätigung durch Secondaries Wait for Replication
  120. 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. 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. 122. Bestätigung durch alle Datenzentren Wait for Replication (Tagging)
  123. 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. 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)
  125. 125. Read Nur Primary primary
  126. 126. Read Read Primary bevorzugt primaryPreferred
  127. 127. Read Read Nur Secondaries secondary
  128. 128. Read Read Read Secondaries bevorzugt secondaryPreferred
  129. 129. Read Read Read Nähester Knoten nearest
  130. 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. 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. 132. Java API & Frameworks
  133. 133. Übersicht Jongo Spring Data MongoDB Morphia Hibernate OGM JPA JDBC MongoDB Java Driver MongoDB
  134. 134. MongoDB Java Treiber
  135. 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. 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. 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. 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. 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. 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. 141. Beispiel: Bestellung > db.order.find( {"items.quantity": ? } )
  142. 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. 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. 144. Jongo
  145. 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. 146. Query in Java as in Mongo Shell
  147. 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. 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);
  149. 149. Morphia
  150. 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. 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. 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. 153. Morphia: Eigene Syntax für Abfragen Morphia Mongo Query = !=, <> >, <, >=,<= in, nin elem … $eq $neq $gt, $lt, $gte, $lte $in, $nin $elemMatch ….
  154. 154. Spring Data MongoDB
  155. 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. 156. Spring Data CrudRepository Spring Data JPA PagingAndSortingRepository Spring Data Neo4j MongoReposito ry GraphRepos itory MongoT em plate JpaRepository Spring Data MongoDB Neo4jTemplate 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. 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. 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. 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. 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. 161. Spring Data MongoDB: Repository Support public interface OrderRepository extends MongoRepository<Order, String> { List<Order> findByItemsQuantity(int quantity); List<Order> findByItemsPriceGreaterThan(double price); }
  162. 162. Spring Data MongoDB: Zusätzliche Unterstützung für… • Map/Reduce & das Aggregation Framework • Das Management von Indexen • Große Dateien mittels GridFS • Geoinformatische Indexe und Abfragen • Optimistisches Locking
  163. 163. Hibernate OGM
  164. 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. 165. Hibernate OGM • Implementiert ein Subset der JPA API • JP-QL Anfragen werden in native Datenbankabfragen übersetzt • Unterstützt Infinispan, EhCache, MongoDB
  166. 166. Architektur von Hibernate OGM Source: http://docs.jboss.org/hibernate/ogm/4.0/reference/en-US/html/ogm-architecture.html#d0e409
  167. 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. 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. 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. 170. Not yet ready for prime time…
  171. 171. Empfehlung
  172. 172. Was sollte ich einsetzen? - „Ready for production“ JPA Hibernate OGM Spring Data MongoDB - Frühes Betastadium - Diskrepanz in API - Aktive Community - Ältestes Framework - Nicht so mächtig wie Spring Morphia Der „bessere“ Treiber Jongo JDBC MongoDB Java Driver - „Ready for production“ - Von MongoDB Inc. unterstützt MongoDB
  173. 173. Getting started… One more thing…
  174. 174. MongoDB User Group https://www.xing.com/net/mongodb-ffm/ http://www.meetup.com/Frankfurt-Rhine-Main-MongoDB-User-Group/
  175. 175. MongoDB Munich 2013 http://www.mongodb.com/events/mongodb-munich-2013/
  176. 176. So Long, and Thanks for All the Fish!
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×