Hour 8. Manipulating MongoDB Documents in a Collection


What You’ll Learn in This Hour:

Image Setting the write concern for database modify requests

Image Inserting new documents into a collection

Image Updating fields in documents that exist in a collection

Image Using upsert to update documents if they exist or insert them if they do not exist

Image Deleting documents from a collection

Image Checking for errors on modification requests


In the previous hours, you worked with methods to retrieve documents from a collection. This hour focuses on modifying a collection by adding, updating, and removing documents. Understanding the methods available for Collection objects to manipulate the documents stored in the collection enables you to initially populate databases, update documents as necessary, and clean up data when it is no longer necessary.

You also learn about the write concern that MongoDB uses to ensure integrity during database write requests. The write concern specifies the level MongoDB uses to ensure that writes are completed before returning a response to the client. The higher the level of concern, the better the integrity, but there is a slight cost in response time.

Understanding the Write Concern

Before connecting to and updating data on a MongoDB database, you need to decide what level of write concern you want to implement. Write concern describes the guarantee that the MongoDB connection provides when reporting on the success of a write operation. The strength of the write concerns determines the level of guarantee.

The basic idea is that a stronger write concern tells MongoDB to wait until the write has successfully been written to disk completely before responding. A weaker write concern might wait only until MongoDB has successfully scheduled the change to be written before responding. The downside of a stronger write concern is that MongoDB waits to respond to the client connection, so write requests are a bit slower.

The write concern can be set to one of the levels in Table 8.1. The level is set on the database connection and applies to all write operations to the database.

Image

TABLE 8.1 Write Concern Levels for MongoDB Database Connections

Configuring Database Connection Error Handling

The getLastError command on Database objects enables you to configure how database connections behave with regard to write concern and timeouts. The getLastError command is a document that describes the options used for database requests. When you make changes to documents in the MongoDB database, the options set in getLastError define how long the connection waits to complete the operation, whether journaling should be used, and so on.

Table 8.2 lists the options you can set in the getLastError command. Use the runCommand() method on the Database object to execute the getLastError command. Consider the syntax for the getLastError command:

myDB.runCommand( { getLastError: 1,
                   w: 1,
                   j: true,
                   wtimeout: 1000
                  } );

Image

TABLE 8.2 Options That Can Be Specified in the getLastError Command of Database Objects

Getting the Status of Database Write Requests

If a write error is detected, that error is stored and can be retrieved using the getLastError command or getLastError() method on the Database object.

The getLastError() method returns null if the last request on the Database object returns true; otherwise, it returns a string containing the error message. For example, to test an add operation, you could use something similar to the following:

mongo = new Mongo('localhost');
wordsDB = mongo.getDB('words');
wordsDB.runCommand( { getLastError: 1, w: 1, j: true, wtimeout: 1000 } );
wordsColl = wordsDB.getCollection('word_stats');
wordsColl.insert({word:"the"});
lastError = wordsDB.getLastError();
if(lastError){
  print("ERROR: " + lastError);
}

The getLastError command returns an object that contains much more information about the error, including the status of the last request, the number of documents modified, and the error message. Table 8.3 lists the properties of the object the getLastError command returned.

Image

TABLE 8.3 Properties of the Object Returned from the getLastError Command on Database Objects

The following shows an example of using the getLastError command:

mongo = new Mongo('localhost');
wordsDB = mongo.getDB('words');
wordsDB.runCommand( { getLastError: 1, w: 1, j: true, wtimeout: 1000 } );
wordsColl = wordsDB.getCollection('word_stats');
wordsColl.insert({word:"the"});
results = wordsDB.runCommand( { getLastError: 1});
if(results.err){
  print("ERROR: " + results.err);
}

Understanding Database Update Operators

When performing updates on objects in MongoDB, you need to specify exactly what fields need to be changed and how they need to be changed. Unlike SQL, in which you create long query strings that define the update, MongoDB enables you to implement simple update objects with operators that define exactly how to change the data in the documents.

You can include as many operators in the update object as you need. The format of the update object appears here:

{
  <operator>: {<field_operation>, <field_operation>, . . .},
  <operator>: {<field_operation>, <field_operation>, . . .}
  . . .
}

For example consider the following object:

{
  name: "myName",
  countA: 0,
  countB: 0,
  days: ["Monday", "Wednesday"],
  scores: [ {id:"test1", score:94}, {id:"test2", score:85}, {id:"test3", score:97}]
}

If you want to increment countA field by 5, increment countB by 1, set the name to "New Name", add Friday to the days array, and sort the scores array by the score field, you would use the following update object:

{
  $inc:{countA:5, countB:1},
  $set:{name:"New Name"},
  $push{days:"Friday},
  $sort:{score:1}
}

Table 8.4 lists the operators that can be used in the update object when updating documents.

Image
Image

TABLE 8.4 Operators That Can Be Specified in the update Object When Performing Update Operations

Adding Documents to a Collection in the MongoDB Shell

Another common task when interacting with MongoDB databases is that of inserting documents into collections. To insert a document, you need to first create a JavaScript object that represents the document you want to store. Insert operations use a JavaScript object because the BSON format that MongoDB uses is based on JavaScript notation.

When you have a JavaScript version of your new document, you can store it in the MongoDB database using the insert() method on an instance of the Collection object that is connected to the database. The following shows the syntax for the insert() method, where the docs parameter can be a single document object or an array of document objects:

insert(docs)

For example, the following shows an example of inserting a simple document into a collection:

mongo = new Mongo('localhost');
myDB = mongo.getDB('myDB');
myColl = myDB.getCollection('myCollection');
myColl.insert({color:"blue", value:7, name:"Ordan"});

Updating Documents in a Collection from the MongoDB Shell

After objects have been inserted into a collection, you need to update them from time to time as the data changes. The update() method on the Collection object enables you to update documents in a collection. This method is versatile, yet fairly easy to implement. The following shows the syntax for the update() method:

update(query, update, upsert, multi)

The query parameter is a document that identifies which document(s) you want to change. The request matches the properties and values in the query with the fields and values of the object; only those matching the query are updated. The update parameter is an object that specifies the changes to make to the documents that match the query. Table 8.4 lists the operators that can be used.

The upsert parameter is a Boolean; when true, if no objects match the query, a new document is created. The multi parameter is also a Boolean; when true, all documents that match the query are updated. When multi is false, only the first document that matches the query is updated.

For example, the following changes the category field value to old for items in the collection for which category currently is new. With upsert set to false, new documents are not created even if no documents have a category of new. With multi set to true, all documents that match are updated:

update({category:"new"}, {$set:{categor:"old"}}, false, true);

When updating multiple documents with the update() call, you can isolate writes to protect the documents from other writes using the $isolated:1 property in the query. This doesn’t provide an all-or-nothing atomic write; it simply inhibits other write processes from updating the same objects you are writing to. For example:

update({category:"new", $isolated:1}, {$set:{category:"old"}}, false, true);

Saving Documents in a Collection Using the MongoDB Shell

The save() method on Collection objects is interesting. It can be used to insert or update a document in the database. However, it is not as directly efficient as insert() or update(). Still, the save() method is easier to implement in some circumstances. For example, when you are making ad-hoc changes to objects already retrieved from MongoDB, you can use save() without having to implement the query and update objects of the update() method.

The following shows the syntax of the save() method, where the doc parameter is the document object to be saved to the collection:

save(doc)

Typically, when using save, the document object either is a completely new JavaScript object that you want to add to the collection or is an object you have already gotten back from the collection and made changes to, and you want to save those changes back to the database.

For example, the following code saves a change to an existing object and inserts a new one:

existingObject = myCollection.findOne({name:"existingObj"});
existingObject.name = "updatedObj";
myCollection.save(existingObj);
myCollection.save({name:"newObj"});

Upserting Documents in Collections Using the MongoDB Shell

Another type of update that you can perform on documents is the upsert. This involves updating the object if it exists and inserting it if it does not. Normal updates do not automatically insert objects because they incur a cost to determine whether the object exists. If you know that an object does exist, then a normal update() is much more efficient; the same is true for an insert() if you know that the document does not already exist.

To implement an upsert, all you need to do is set the upsert parameter in the update() method to true. This tells the request to try to update the object if it exists; otherwise, a new object with field values defined in the update parameter of the update() method is inserted.

For example, the following code performs an update if a document that has a color field of azure exists in the database; otherwise, it is created:

update({color:"azure"}, {$set:{red:0, green:127, blue:255}}, true, false);


Watch Out!

To avoid inserting the same document more than once, use upsert: true only if the query field is uniquely indexed.


Deleting Documents from a Collection Using the MongoDB Shell

You will need to delete documents from your MongoDB collection to keep space consumption down, improve performance, and keep things clean. The remove() method on Collection objects makes deleting documents from a collection simple. The syntax for the remove() method follows:

remove([query], [justOne])

The query parameter is a document that identifies which document(s) you want to delete. The request matches the properties and values in the query with the fields and values of the object; only those that match the query are updated. If no query is provided, all the documents in the collection are deleted.

The justOne parameter is a Boolean. When true, only the first document that matches the query is deleted. If no query or justOne parameter is specified, all documents in the collection are deleted.

For example, to delete all documents in the words_stats collection, you could use

collection = myDB.getCollection('word_stats');
collection.remove();

The following code deletes all words that start with a from the words_stats collection:

collection = myDB.getCollection('word_stats');
collection.remove({first:'a'}, false);

The following deletes only the first word that starts with a from the words_stats collection:

collection = myDB.getCollection('word_stats');
collection.remove({first:'a'}, true);

Summary

The Collection object in the MongoDB shell provides several methods for inserting, accessing, modifying, and removing documents from collections. You can insert documents into the database using insert(), save(), and even update() with upsert. The update() and save() methods enable you to update existing documents. You use the remove() method to delete one or more documents.

In this hour, you also learned about the write concern that MongoDB uses to provide different levels of integrity to database update requests. The write concern specifies the level that MongoDB uses to ensure that writes are completed before returning a response to the client. The higher the level of concern, the better the integrity, but there is a slight cost in response time. You also learned how to set the write concern and other options in the getLastError command, as well as how to find and handle errors that result because of timeouts or write concern issues.

Q&A

Q. Are writes to the MongoDB dataset atomic?

A. Sort of. Only one request can modify a collection at the same time. This ensures that writes to a single collection are atomic. However, MongoDB does not provide a direct method to ensure that writes to documents in multiple collections are atomic; you must do that programmatically in your application.

Workshop

The workshop consists of a set of questions and answers designed to solidify your understanding of the material covered in this hour. Try answering the questions before looking at the answers.

Quiz

1. Which write concern gives the highest level of integrity?

2. How do you limit the update option to only a single document?

3. True or false: You can use the save() method on Collection objects only to save existing documents.

4. How do you insert multiple documents at the same time into a collection?

Quiz Answers

1. 1

2. Set the multi parameter of the update() method to false.

3. False.

4. Pass an array of JavaScript objects to the insert() method on the Collection object.

Exercises

1. Find at least two new words that you want to add to the word_stats collection in the example dataset. Create a shell script that uses the insert() method to add those words.

2. Create a shell script that uses the update() method to add a field named category with a value of exercise to the words you added in Exercise 1.

3. Create a shell script that retrieves words with a category of exercise and uses remove() to delete them.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.14.248.69