Sunday, January 24, 2016

Mongo DB getting started - CRUD operations - java

1. Intro

First of all we have to add mongo dependency into pom.xml file :
<dependency>
  <groupId>org.mongodb</groupId>
  <artifactId>mongo-java-driver</artifactId>
  <version>3.2.0</version>
</dependency>

After that, we can connect to mongo db  in our application :
MongoClient mongoClient = new MongoClient();
MongoDatabase db = mongoClient.getDatabase("course");
MongoCollection<Document> coll=db.getCollection("findTest");

Also I wrote several simple functions which can be useful :

public int getRandomInt() {
    int result=(int)Math.round(Math.random()*1000);
    return result;
}

public List<Document> getAllDocs() {
    List<Document> docs=coll.find().into(new ArrayList<Document>());
    return docs;
}

public void printList(String comment, List<?> list) {
    System.out.println(comment + " " + Arrays.toString(list.toArray()));

}

2. Insert

Now let's try to insert some documents into our test collection.
Before inset, first we have to create a Document. To populate Document structure we can use "append" method :

coll.drop();
coll.insertOne(new Document().append("name","Fernando").append("age", 41));
coll.insertOne(new Document().append("name",new Document("fist_name","Huan").append("second_name","Sebastyan")).append("age",40));

Document john=new Document().append("name","John").append("age",32);
Document smith=new Document().append("name","Smith").append("age",25);
coll.insertMany(Arrays.asList(john, smith));

printList("inserted documents:",getAllDocs());

Results:
inserted documents: [
Document{{_id=56a4957ac6e31a20f88dbfdc, name=Fernando, age=41}}, Document{{_id=56a4957ac6e31a20f88dbfdd,
                     name=Document{{fist_name=Huan, second_name=Sebastyan}},
                     age=40}},
Document{{_id=56a4957ac6e31a20f88dbfde, name=John, age=32}}, Document{{_id=56a4957ac6e31a20f88dbfdf, name=Smith, age=25}}
]


3. Find - basic operations

Let's populate test collection :
coll.drop();
for (int i=0;i<10;i++) {
    Document doc=new Document("x",i);
    coll.insertOne(doc);
}

To get count of documents in collection : 
long cnt=coll.count();
System.out.println("Count of documents:"+cnt);

To get first element : 
Document firstDoc= coll.find().first();
System.out.println("First document :"+firstDoc.toJson());

To get all documents : 
List<Document> allDoc=coll.find().into(new ArrayList<Document>());
System.out.println("Array with collection documents :"+Arrays.toString(allDoc.toArray()));


Working with cursors : 
MongoCursor<Document> cursor=coll.find().iterator();

try {
    while (cursor.hasNext()) {
        Document doc=cursor.next();
        System.out.println(" document from cursor "+doc.toJson());
    }
} finally {
    cursor.close();
}

4. Find - filtering
Of course, most often operation - is to filter "find" results by some criteria. For that, we have to populate a Document with "criteria". Another option - is using "builders" from Filters class:

Let's create a test collection :

coll.drop();
for (int i=0;i<10;i++) {
    for (int j=0;j<5;j++) {
        Document doc=new Document("x",i).append("y",j);
        coll.insertOne(doc);
    }

}

Just a simple filter : 
Document simpleFilter=new Document("x",5);
List<Document> filteredDocs=coll.find(simpleFilter).into(new ArrayList<Document>());
System.out.println("Filtered by [x=5] documents:" + Arrays.toString(filteredDocs.toArray()));


More complex filter : 
Document complexFilter=new Document("x",5).append("y", new Document("$gt", 3));
filteredDocs=coll.find(complexFilter).into(new ArrayList<Document>());
System.out.println("Filtered by [x=5 && y>3] documents:" + Arrays.toString(filteredDocs.toArray()));


Using Filter builder : 
Bson bsonFilter= Filters.and(Filters.eq("x", 5), Filters.lt("y", 3));
filteredDocs=coll.find(bsonFilter).into(new ArrayList<Document>());
System.out.println("Filtered by [x=5 && y<3] documents:" + Arrays.toString(filteredDocs.toArray()));

Results : 
Filtered by [x=5] documents:[Document{{_id=56a49896c6e31a21ddc31eee, x=5, y=0}}, Document{{_id=56a49896c6e31a21ddc31eef, x=5, y=1}}, Document{{_id=56a49896c6e31a21ddc31ef0, x=5, y=2}}, Document{{_id=56a49896c6e31a21ddc31ef1, x=5, y=3}}, Document{{_id=56a49896c6e31a21ddc31ef2, x=5, y=4}}]
Filtered by [x=5 && y>3] documents:[Document{{_id=56a49896c6e31a21ddc31ef2, x=5, y=4}}]
Filtered by [x=5 && y<3] documents:[Document{{_id=56a49896c6e31a21ddc31eee, x=5, y=0}}, Document{{_id=56a49896c6e31a21ddc31eef, x=5, y=1}}, Document{{_id=56a49896c6e31a21ddc31ef0, x=5, y=2}}]

5. Find - projection

Sometimes, in result set we don't need all fields, but only some specific. For that purpose we can use "projection" documents, in which we will specify which fields we want to show or hide. And, also, like with filters, we can use builders "Projections". 

Let's create one test object : 
coll.drop();
coll.insertOne(new Document("name", "Joe").append("age", 32));

Filter : 
Bson filter=new Document("name","Joe");

Projection with hiding fields "age" and "_id" : 
Bson projection=new Document().append("age",0).append("_id", 0);
List<Document> docs= coll.find(filter).projection(projection).into(new ArrayList<Document>());
System.out.println("filtered with projection[name]:"+Arrays.toString(docs.toArray()));

Hiding of "_id" field using builder : 
projection= Projections.exclude("_id");
docs= coll.find(filter).projection(projection).into(new ArrayList<Document>());
System.out.println("filtered with projection[name,age]:"+Arrays.toString(docs.toArray()));

Hiding of "_id" field and including "age" filed using builder :
projection= Projections.fields( Projections.excludeId(), Projections.include("age")); docs= coll.find(filter).projection(projection).into(new ArrayList<Document>()); System.out.println("filtered with projection[age]:"+Arrays.toString(docs.toArray()));

Results : 
filtered with projection[name]:[Document{{name=Joe}}]
filtered with projection[name,age]:[Document{{name=Joe, age=32}}]
filtered with projection[age]:[Document{{age=32}}]


6. Find - sorting

To sort by some criteria, as usual we have 2 options : 1. just create a "sort document" 2. use builder: 

Create test collection: 
coll.drop();
for (int i=0;i<1000;i++) {
    coll.insertOne(new Document("x",getRandomInt()).append("y", getRandomInt()).append("z", getRandomInt()));
}

Filter:
Document filterXlt10=new Document("x", new Document("$lt",10) );

Sort document : 
Document sortByXasc=new Document("x",1);
List<Document> docs=coll.find().filter(filterXlt10).sort(sortByXasc).into(new ArrayList<Document>());
printList("filtered by x<10 and sorted by x asc",docs);
filtered by x<10 and sorted by x asc [
Document{{_id=56a49c2fc6e31a231094c9a1, x=2, y=582, z=852}}, Document{{_id=56a49c2fc6e31a231094c958, x=3, y=688, z=922}}, Document{{_id=56a49c2fc6e31a231094c95e, x=3, y=74, z=396}}, Document{{_id=56a49c2fc6e31a231094c9b2, x=3, y=736, z=131}}, Document{{_id=56a49c2fc6e31a231094c9f4, x=3, y=35, z=856}}, Document{{_id=56a49c2fc6e31a231094cba5, x=4, y=369, z=14}}, Document{{_id=56a49c2fc6e31a231094cb02, x=5, y=990, z=816}}, Document{{_id=56a49c2ec6e31a231094c8d8, x=7, y=535, z=501}}, Document{{_id=56a49c2fc6e31a231094cb75, x=7, y=34, z=933}}, Document{{_id=56a49c2fc6e31a231094cbb4, x=8, y=795, z=878}}, Document{{_id=56a49c30c6e31a231094cbd0, x=8, y=989, z=255}}, Document{{_id=56a49c2fc6e31a231094ca17, x=9, y=486, z=603}}, Document{{_id=56a49c2fc6e31a231094cacc, x=9, y=843, z=457}}]
Sorting using builder : Bson sortYDesc= Sorts.descending("y"); docs=coll.find().filter(filterXlt10).sort(sortYDesc).into(new ArrayList<Document>()); printList("filtered by x<10 and sorted by y desc",docs);

filtered by x<10 and sorted by y desc [
Document{{_id=56a49c2fc6e31a231094cb02, x=5, y=990, z=816}}, Document{{_id=56a49c30c6e31a231094cbd0, x=8, y=989, z=255}}, Document{{_id=56a49c2fc6e31a231094cacc, x=9, y=843, z=457}}, Document{{_id=56a49c2fc6e31a231094cbb4, x=8, y=795, z=878}}, Document{{_id=56a49c2fc6e31a231094c9b2, x=3, y=736, z=131}}, Document{{_id=56a49c2fc6e31a231094c958, x=3, y=688, z=922}}, Document{{_id=56a49c2fc6e31a231094c9a1, x=2, y=582, z=852}}, Document{{_id=56a49c2ec6e31a231094c8d8, x=7, y=535, z=501}}, Document{{_id=56a49c2fc6e31a231094ca17, x=9, y=486, z=603}}, Document{{_id=56a49c2fc6e31a231094cba5, x=4, y=369, z=14}}, Document{{_id=56a49c2fc6e31a231094c95e, x=3, y=74, z=396}}, Document{{_id=56a49c2fc6e31a231094c9f4, x=3, y=35, z=856}}, Document{{_id=56a49c2fc6e31a231094cb75, x=7, y=34, z=933}}]

Complex sorting: 
Bson sortXascYdesc=Sorts.orderBy(Sorts.ascending("x"), Sorts.descending("y"));
docs=coll.find().filter(filterXlt10).sort(sortXascYdesc).into(new ArrayList<Document>());
printList("filtered by x<10 and sorted by x asc and y desc",docs); 

filtered by x<10 and sorted by x asc and  y desc [
Document{{_id=56a49c2fc6e31a231094c9a1, x=2, y=582, z=852}}, Document{{_id=56a49c2fc6e31a231094c9b2, x=3, y=736, z=131}}, Document{{_id=56a49c2fc6e31a231094c958, x=3, y=688, z=922}}, Document{{_id=56a49c2fc6e31a231094c95e, x=3, y=74, z=396}}, Document{{_id=56a49c2fc6e31a231094c9f4, x=3, y=35, z=856}}, Document{{_id=56a49c2fc6e31a231094cba5, x=4, y=369, z=14}}, Document{{_id=56a49c2fc6e31a231094cb02, x=5, y=990, z=816}}, Document{{_id=56a49c2ec6e31a231094c8d8, x=7, y=535, z=501}}, Document{{_id=56a49c2fc6e31a231094cb75, x=7, y=34, z=933}}, Document{{_id=56a49c30c6e31a231094cbd0, x=8, y=989, z=255}}, Document{{_id=56a49c2fc6e31a231094cbb4, x=8, y=795, z=878}}, Document{{_id=56a49c2fc6e31a231094cacc, x=9, y=843, z=457}}, Document{{_id=56a49c2fc6e31a231094ca17, x=9, y=486, z=603}}]


7. Find - limit and skip 

Everything is very simple here : 2 additional methods "limit" and "skip" for that : 

coll.drop();
for (int i=0;i<1000;i++) {
    coll.insertOne(new Document("x",i).append("y", getRandomInt()).append("z", getRandomInt()));
}
List<Document> docs=coll.find().limit(5).skip(20).into(new ArrayList<Document>());
printList("limit=5, skip=20",docs);

limit=5, skip=20 [
Document{{_id=56a49d1ec6e31a2377101042, x=20, y=629, z=576}}, 
Document{{_id=56a49d1ec6e31a2377101043, x=21, y=152, z=835}}, 
Document{{_id=56a49d1ec6e31a2377101044, x=22, y=599, z=833}}, 
Document{{_id=56a49d1ec6e31a2377101045, x=23, y=252, z=136}}, 
Document{{_id=56a49d1ec6e31a2377101046, x=24, y=949, z=25}}]


8.Update

For update operation we need to define 2 objects : FILTER and VALUE. 
Format of operation : 
UPDATE(FILTER-which documents we want to update,VALUE-what exactly we have to put)
FILTER document - the same document which we use for FIND operation.  

VALUE document - it can just another NewDocument - in that case, document(s) which was(were) found by FILTER statement will be replaced with NewDocument. Another option - is using "$set" document : in that case we can identify what exactly we want to replace. 

Let's create a test collection : 
coll.drop();
for (int i=0;i<5;i++) {
    coll.insertOne(new Document("_id",i).append("x", i));
}
docs=getAllDocs();
printList("original collection",docs);
original collection [
Document{{_id=0, x=0}}, 
Document{{_id=1, x=1}}, 
Document{{_id=2, x=2}}, 
Document{{_id=3, x=3}}, 
Document{{_id=4, x=4}}]


Full replace of old document with the new one: 
coll.replaceOne(Filters.eq("x", 3), new Document("x", 333).append("state", "replaced"));
docs=getAllDocs();
printList("collection with replacing [_id=3] :", docs);

collection with replacing [_id=3] : [
Document{{_id=0, x=0}}, 
Document{{_id=1, x=1}}, 
Document{{_id=2, x=2}}, 
Document{{_id=3, x=333, state=replaced}}, 
Document{{_id=4, x=4}}]


Update of just one field using $set 
coll.updateOne(Filters.eq("_id", 2), new Document("$set", new Document("state", "updated")));
docs=getAllDocs();
printList("collection with updating [_id=2] :", docs);

collection with updating [_id=2] : [
Document{{_id=0, x=0}}, 
Document{{_id=1, x=1}}, 
Document{{_id=2, x=2, state=updated}}, 
Document{{_id=3, x=333, state=replaced}}, 
Document{{_id=4, x=4}}]


Using "upsert" option : if record does not exists - it will be created.
coll.updateOne(Filters.eq("_id", 5), new Document("$set", new Document("state", "upserted")), new UpdateOptions().upsert(true));
docs=getAllDocs();
printList("collection with upserted [_id=5] :", docs);

collection with upserted [_id=5] : [
Document{{_id=0, x=0}}, 
Document{{_id=1, x=1}}, 
Document{{_id=2, x=2, state=updated}}, 
Document{{_id=3, x=333, state=replaced}}, 
Document{{_id=4, x=4}}, 
Document{{_id=5, state=upserted}}]


Update many records : 
coll.updateMany(new Document("_id",new Document("$lt",3)), new Document("$inc",new Document("x",10)));
docs=getAllDocs();
printList("collection with updated by [_id<3] set x=x+10",docs);

collection with updated by [_id<3] set x=x+10 [
Document{{_id=0, x=10}}, 
Document{{_id=1, x=11}}, 
Document{{_id=2, x=12, state=updated}}, 
Document{{_id=3, x=333, state=replaced}}, 
Document{{_id=4, x=4}}, 
Document{{_id=5, state=upserted}}]


9. Delete

Execution of delete is similar to "find" - we just need to specify how to find the object(s) , which of course will be deleted. 

Let's create a test collection : 
coll.drop();
for (int i=0;i<5;i++) {
    coll.insertOne(new Document("_id",i).append("x", i));
}

Original collection: 
docs=getAllDocs();
printList("original collection", docs);

original collection [
Document{{_id=0, x=0}}, 
Document{{_id=1, x=1}}, 
Document{{_id=2, x=2}}, 
Document{{_id=3, x=3}}, 
Document{{_id=4, x=4}}]
Delete several documents: 
coll.deleteMany(new Document("_id", new Document("$gt", 3)));docs=getAllDocs();
printList("deleted by DeleteMany by condition[_id>3]", docs);

deleted by DeleteMany by condition[_id>3] [
Document{{_id=0, x=0}}, 
Document{{_id=1, x=1}}, 
Document{{_id=2, x=2}}, 
Document{{_id=3, x=3}}]

Delete just one document: 
coll.deleteOne(new Document("_id", new Document("$gt",0)));docs=getAllDocs();
printList("deleted by DeleteOne by condition[_id>0]", docs); 

deleted by DeleteOne by condition[_id>0] [

Document{{_id=0, x=0}}, 

Document{{_id=2, x=2}}, 

Document{{_id=3, x=3}}]


10. Aggregation
Pipe for aggregation we can create in java code, or by parsing mongo documents : 
List<Document> pipeline=Arrays.asList(
        new Document("$group",
                 new Document("_id","$state").
                 append("totalPop", new Document("$sum", "$pop"))),
        new Document("$match",
                 new Document("totalPop",new Document("$gt",500000)))
);
List<Document> docs =coll.aggregate(pipeline).into(new ArrayList<Document>());
printList("aggregation:population>500000:",docs);




pipeline=Arrays.asList(Document.parse("{'$group':{'_id':'$state','totalPop':{'$sum':'$pop'}}}")
                      ,Document.parse("{'$match':{'totalPop': {'$lt':500000}}}")

);
docs =coll.aggregate(pipeline).into(new ArrayList<Document>());
printList("aggregation:population<500000:",docs);


result : 

aggregation:population>500000: [Document{{_id=CT, totalPop=661324}}, Document{{_id=CA, totalPop=953386}}, Document{{_id=NJ, totalPop=847495}}]
aggregation:population<500000: [Document{{_id=NY, totalPop=485267}}]








No comments:

Post a Comment