Skip to content
Zita Szupera edited this page Jun 22, 2015 · 1 revision

NOTES FROM THE COURSE

Week 2: CRUD operations

Introduction / Repetition

As we learnt last week: MongoDB stores documents as BSON-s, which are binary representations of JSON-s. In a BSON, keys and values can be only BSON types (specification: http://bsonspec.org/). These documents are stored in collections, so we have to call our CRUD operations on collections.

However MongoDB does not have a query language like relational databases have SQL, CRUD operations are mapped by functions/methods in different drivers and interfaces (like the mongo shell).

This week's agenda: CRUD in the mongo shell, CRUD in the Java driver.

CRUD - mongo shell

On the mac terminal:
-ctrl + a: cursor jumps at the start of the current line
-ctrl + i: cursor jumps at the end of the current line
In the mongo shell:
help: helping command
help keys: key combinations, and some other info about the commands in mongo

Insert

We can insert new documents with the insert method.

Usage: db.<collection name>.inset(<document to be inserted>) where

  • db is the handle of the current database
  • collection is the name of the collection which will store the inserted document, if it is not exists, the insert method will create it
  • document is a BSON document
About types: MongoDB BSON provides support for additional data types than JSON. Drivers provide native support for these data types in host languages and the mongo shell also provides several helper classes to support the use of these data types in the mongo JavaScript shell. (quote from MongoDB documentation)
More information about the _id field:
- the field is immutable
- the field is generated in a way that in almost all cases the _id is globally unique (so not just in the collection)

Select

We basically have two methods for selecting: find and findOne. The difference is quite obvious: find can return multiple documents while findOne can only return one. (If you specify criteria which gives back more than one document (or not specify at all) than you get a random document from the results.)

Usage: similar to the insert method, but this time we have more arguments:

  • 1st (optional): query criteria, BSON document
  • 2nd (optional): column list, BSON document So a find method looks like this: db.<collection name>.find([<query critera>], [<column list>])
db.<collection name>.find() returns a cursor to the results, if we don't assign this variable, the shell will display the results with paging. It iterates automatically the first 20 results, then we have to type 'it' for the next 20, and so on.
db.<collection name>.find().pretty() displays the result documents with better intendation.

Criteria

Query by example

Querying by example is easy, we can specify our conditions in a BSON like this {[<field name> : <value>][0...*]}

Inequalities, ranges

The mongo shell has the following operators:

  • < is $lt
  • <= is $lte
  • is $gt

  • = is $gte

Usage: {[<field name> : {[<operator> : <value>][0...*]}][0...*]}

Comparison of strings:

  • Sorting strings in MongoDB: Strings are represented in UTF-8, and sorting is based on the numeric (byte) representation of the characters of the string. MongoDB does not support locals.
  • B < Bob because Bob is longer
Exisctence

If we want to look for documents which have or not a have a specific field, we can use the $exists operator. It is important to mention, that if a field is empty, it does not missing. Usage: {<field name> : {$exists : <true or false>}}

Reular expressions

We can write regular expressions in the $regex field. MongoDB uses Perl compatible regular expressions.

Type

Since MongoDB is schemaless, we can have different value types for the same field in a collection. We can specify in a query, that we only want to list documents with fields with given types, we can use the $type operator for this.

Usage: {<filed name> : {$type : <BSON type number>}}

List of BSON type numbers: http://docs.mongodb.org/manual/reference/bson-types/

Criteria inside of arrays

We have learnt about two operators which help querying inside of arrays: $in/$all operator checks if ANY/ALL of the given values are in the specified array.

Usage: {<field name (array type)> : {<$in or $all> : [<list of values>]}}

Sice MongoDB is schemaless it is possible that we have documents in a collection with the same field but different datatypes. So if we define a criterion three things can happen:
- the document does not have the given field -> the document won't be in the resultset
- the document has the given field, but with a different datatype (e.g.: string instead of integer) -> the document won't be in the resultset
HOWEVER there is one exception to this, the searching is polymorphic over arrays and non-arrays, which means, if we have a criterion on an array, but the given document has a non-array type instead, the search will also be performed (in other words the value will be treated as a one-element-array).
- the document has the given field with the given datatype -> evaluation against criterion
Criteria on embedded documents

If we have a schema with embedded documents, we can use the 'dot notation' for searching.

Usage: .

Look at the following schema: {"email" : {"work" : "email1", "private" : "email2"}}
It sounds logical to write this as a search criterion: {"email" : {"work" : "[email protected]", "private" : "[email protected]"}} it is also correct. The problem with this, that the order of the field of the inside document (work, private), is matter, so if I have a document with the same values, but the fields are in different order (private, work), the document won't be in the resultset.
Concatening criteria

We have seen, that we can define criteria in a BSON document, the relationship between the items of the document is "and". However MongoDB also has an explicit $and operator, it has some implementation differences, it is not as performant. Also, if want to define criteria where the relationship between the criteria is "or" we can use the $or operator.

Usage: {<$or or $and> : [{ : <criterion/criteria>}[0...*][,]]}

If we define more document with the same field (column) in the list, only the last one will have effect.

Cursors, sort and limit

Cursors help us processing the result of a query in an efficient way. MongoDB cursors work familiar to any other kind of cursor:

cur = db.collection.find(); null; //this way the first 20 result won't get fetched (which is the default behavior)
cur.sort({<field name> : <-1 or 1>}).limit(<int>).skip(<int>); null; //sort and limit is processed by the server, can only be invoked before any data has been fetched
while (cur.hasNext()) {
   cur.next();
}

Projection

We can do projection in the 2nd parameter of find/findOne method (it is optional).

Usage: {{ : <1 (include) or 0 (exclude)>}[0...*]} If we say nothing about a filed, it will be left out, the only exception is, if we want to exclude the _id field, we have to explicitly exclude the field (it is also because MongoDB is designed as an object store).

Update

Let's see how to update documents in MongoDB!

We can use the update method for modification like this db.<collection name>.update(<parameters in BSONs>)

What are the most important parameters?

  • Which document(s) do we want to modify? -> 1st parameter, required, same as for searching
  • Which field(s) do we want to modify? -> 2nd parameter, required
    • If we just define the fields to be modified and their new value (in a BSON), we will get the wholesale replacement of the fields (it is because MongoDB is designed as an object store)
    • If we don't want that, we can use the $set and $unset operators. They work just like any other operators, the $set will add or modify the given field, the $unset will remove it.

Other parameters

  • MongoDB supports upserts, which can be enabled by the 3rd parameter like this {upsert: true} however this is optional.
    • If a new document is inserted, it will have all the fields that are determined by the first two parameters of the update method. (Underdetermined fields will be left out.)
db.collection.update({"age" : {$gt : 50}, {"name" : "William"}, {upsert : true}}) //the new document will have an _id and name field, nut no age (because age in underdetermined)
  • By default update modifies only one document, regardless how many matches the criteria, if we want to update more docs, we need to specify the 4th parameter like this {multi : true} however this is optional.

Update operations

Useful operations for updates: http://docs.mongodb.org/manual/reference/operator/update-field/

Updating arrays

Useful array operators: http://docs.mongodb.org/manual/reference/operator/update-array/

Remove

We can delete elements with the remove function, we can pass the criteria in a BSON, the same way as seen in the Select section.

Usage: db.<collection name>.remove({<criteria>})

db.collection.remove({}) removes all elements of the given collection.

db.collection.drop() also removes all elements of the given collection, but it also delets all the metadata (e.g.: indexes).

Even if you want to empty a collection, and then later fill it again, remove({}) is not recommended, use drop() instead, and create the metadata again, if necessary.

Java driver

Finally, I will write briefly about the Java driver and the CRUD operations in it.

Connection

There are many ways for connecting to a database, there are many options however I will only present here one:

MongoClient mongoClient = new MongoClient(new MongoClientURI(mongoURIString)); //e.g.: mongodb://localhost

Getting a database handler:

MongoDatabase blogDatabase = mongoClient.getDatabase("blog");

Getting collection:

postsCollection = blogDatabase.getCollection("posts");

If we have a reference to a collection, we can start modify it.

CRUD

CRUD operations are Java methods, which accept BSON-s as parameters. The Java driver comes with a BSON library, we used the Document class.

Let's see an example of a Document (the example if from homework):

Document post = new Document("_id", new ObjectId())
                            .append("title", title)
                            .append("author", username)
                            .append("body", body)
                            .append("permalink", permalink)
                            .append("comment", new BasicDBList())
                            .append("date", new Date());

List of MongoCollection's functions: http://api.mongodb.org/java/3.0/com/mongodb/client/MongoCollection.html

Operators

Instead of operators, the Java driver has static operations. For example, the query operators are in the Filters class.

Projections

Projection can also be done with static methods, use the Projections class for that.

Sorting

Sorts static class.