-
Notifications
You must be signed in to change notification settings - Fork 0
Week2
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.
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
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)
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.
Querying by example is easy, we can specify our conditions in a BSON like this {[<field name> : <value>][0...*]}
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
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>}}
We can write regular expressions in the $regex
field. MongoDB uses Perl compatible regular expressions.
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/
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
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.
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 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();
}
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).
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>)
- 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.
- 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.)
- If a new document is inserted, it will have all the fields that are determined by the first two parameters of the
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.
Useful operations for updates: http://docs.mongodb.org/manual/reference/operator/update-field/
Useful array operators: http://docs.mongodb.org/manual/reference/operator/update-array/
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.
Finally, I will write briefly about the Java driver and the CRUD operations in it.
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 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
Instead of operators, the Java driver has static operations. For example, the query operators are in the Filters
class.
Projection can also be done with static methods, use the Projections
class for that.
Sorts
static class.