14
Manipulating MongoDB Documents from Node.js

In Chapter 13, “Getting Started with MongoDB and Node.js,” you learned the fundamentals of using the MongoDB Node.js driver to manage and manipulate databases and collections. This chapter expands on those concepts to include manipulation of documents within collections. The MongoDB Node.js driver provides a lot of functionality in the Collection class, described in Chapter 13, that allows you to insert, access, modify, and remove documents from collections.

This chapter is broken down into sections that describe the basic document management tasks that you perform on collections, including inserts and deletes. This chapter introduces you to the options that control the behavior of write requests to the database. You also learn about the update structure that MongoDB uses to update documents rather than the long, complex query strings you may have seen in SQL.

Understanding Database Change Options

Several methods discussed in this chapter modify the MongoDB database. When you make changes to the database, the MongoDB Node.js driver needs to know how to handle the connection during the change process. For that reason, each method that changes the database allows you to pass in an optional options parameter that can specify some or all of the properties defined in Table 14.1.

Table 14.1 Options that can be specified in the options parameter of database changing requests to define behavior

Option

Description

w

Specifies the write concern level for database connections. See Table 13.1 for the available values.

wtimeout

Specifies the amount of time in milliseconds to wait for the write concern to finish. This value is added to the normal connection timeout value.

fsync

A Boolean that, when true, indicates that write requests wait for fsync to finish before returning.

journal

A Boolean that, when true, indicates that write requests wait for the journal sync to complete before returning.

serializeFunctions

A Boolean that, when true, indicates that functions attached to objects will be serialized when stored in the document.

forceServerObjectId    

A Boolean that, when true, indicates that any object ID (_id) value set by the client is overridden by the server during insert.

checkKeys

A Boolean that, when true, causes the document keys to be checked when being inserted into the database. The default is true. (Warning: Setting this to false can open MongoDB up for injection attacks.)

upsert

A Boolean that, when true, specifies that if no documents match the update request, a new document is created.

multi

A Boolean that, when true, specifies that if multiple documents match the query in an update request, all documents are updated. When false, only the first document found is updated.

new

A Boolean that, when true, specifies that the newly modified object is returned by the findAndModify() method instead of the pre-modified version. The default is false.

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 where you create long query strings that define the update, MongoDB allows you to implement an update object 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 is shown 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 the countA field by 5, increment countB by 1, set 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 14.2 lists the operators that can be used in the update object when updating documents.

Table 14.2 Operators that can be specified in the update object when performing update operations

Operator

Description

$inc

Increments the value of the field by the specified amount.

Operation format: field:inc_value

$rename

Renames a field.

Operation format: field:new_name

$setOnInsert

Sets the value of a field when a new document is created in the update operation.

Operation format: field:value

$set

Sets the value of a field in an existing document.

Operation format: field:new_value

$unset

Removes the specified field from an existing document.

Operation format: field:""

$

Acts as a placeholder to update the first element that matches the query condition in an update.

$addToSet

Adds elements to an existing array only if they do not already exist in the set.

Operation format: array_field:new_value

$pop

Removes the first or last item of an array. If the pop_value is -1, the first element is removed. If the pop_value is 1, the last element is removed.

Operation format: array_field:pop_value

$pullAll

Removes multiple values from an array. The values are passed in as an array to the field name.

Operation format: array_field:[value1, value2, ...]

$pull

Removes items from an array that match a query statement. The query statement is a basic query object with field names and values to match.

Operation format: array_field:[<query>]

$push

Adds an item to an array.

Simple array format: array_field:new_value

Object array format: array_field:{field:value}

$each

Modifies the $push and $addToSet operators to append multiple items for array updates.

Operation format: array_field:{$each:[value1, ...]}

$slice

Modifies the $push operator to limit the size of updated arrays.

$sort

Modifies the $push operator to reorder documents stored in an array.

Operation format: array_field:{$slice:<num>}

$bit

Performs bitwise AND and OR updates of integer values.

Operation format:

integer_field:{and:<integer>}
integer_field:{or:<integer>}

Adding Documents to a Collection

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

Once 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 connected to the database. The following shows the syntax for the insert() method:

insert(docs, [options], callback)

The docs parameter can be a single document object or an array of document objects. The options parameter specifies the database change options described previously in Table 14.1. The callback function is required if you are implementing a write concern in the options. The first parameter of the callback function is an error, and the second parameter is an array of the documents inserted into the collection.

Listing 14.1 illustrates a basic example of inserting documents. Lines 2–9 show a function that accepts the Collection object and an object to insert. The insert() method is called, and the resulting array of inserted objects (one at time in this case) is displayed on the console. Lines 10–13 open up the connection to the MongoDB server, clear out the nebulae collection, and then re-create it to provide a clean slate. Then lines 14–19 call addObject() for a series of JavaScript objects describing nebulae.

Listing 14.1 doc_insert.js: Inserting documents into a collection

01 var MongoClient = require('mongodb').MongoClient;
02 function addObject(collection, object){
03   collection.insert(object, function(err, result){
04     if(!err){
05       console.log("Inserted : ");
06       console.log(result);
07     }
08   });
09 }
10 MongoClient.connect("mongodb://localhost/", function(err, db) {
11   var myDB = db.db("astro");
12   myDB.dropCollection("nebulae");
13   myDB.createCollection("nebulae", function(err, nebulae){
14     addObject(nebulae, {ngc:"NGC 7293", name:"Helix",
15       type:"planetary",location:"Aquila"});
16     addObject(nebulae, {ngc:"NGC 6543", name:"Cat's Eye",
17       type:"planetary",location:"Draco"});
18     addObject(nebulae, {ngc:"NGC 1952", name: "Crab",
19       type:"supernova",location:"Taurus"});
20   });
21 });

Listing 14.1 Output doc_insert.js: Inserting documents into a collection

Inserted :
{ result: { ok: 1, n: 1 },
  ops:
   [ { ngc: 'NGC 7293',
       name: 'Helix',
       type: 'planetary',
       location: 'Aquila',
       _id: 598e04b98e397c0f8464bb99 } ],
  insertedCount: 1,
  insertedIds: [ 598e04b98e397c0f8464bb99 ] }
Inserted :
{ result: { ok: 1, n: 1 },
  ops:
   [ { ngc: 'NGC 6543',
       name: 'Cat's Eye',
       type: 'planetary',
       location: 'Draco',
       _id: 598e04b98e397c0f8464bb9a } ],
  insertedCount: 1,
  insertedIds: [ 598e04b98e397c0f8464bb9a ] }
Inserted :
{ result: { ok: 1, n: 1 },
  ops:
   [ { ngc: 'NGC 1952',
       name: 'Crab',
       type: 'supernova',
       location: 'Taurus',
       _id: 598e04b98e397c0f8464bb9b } ],
  insertedCount: 1,
  insertedIds: [ 598e04b98e397c0f8464bb9b ] }

Getting Documents from a Collection

A common task that you perform on data stored in a MongoDB is retrieving one or more documents. For example, consider product information for products on a commercial website. The information is stored once but retrieved many times.

The retrieval of data sounds simple; however, it can become complex as you filter, sort, limit, and aggregate the results. In fact, Chapter 15, “Accessing MongoDB from Node.js,” is entirely devoted to the complexities of retrieving data.

This section introduces you to the simple basics of the find() and findOne() methods of the Collection object to make it easier to understand the code examples in this chapter. The syntax for find() and findOne() are shown here:

find(query, [options], callback)
findOne(query, [options], callback)

Both find() and findOne() accept a query object as the first parameter. The query object contains properties that are matched against fields in the documents. Documents that match the query are included in the list. The options parameter is an object that specifies everything else about the search for documents, such as the limit, sort, and what to return.

The callback function is where find() and findOne() differ. The find() method returns a Cursor object that can be iterated on to retrieve documents, whereas the findOne() method returns a single object.

Listing 14.2 illustrates the basic use of handling the results of find() and findOne(). The code in lines 5–10 implements find(). Notice that the result is a Cursor object. To display the results, the toArray() method is called, which iterates through the Cursor object and builds a basic JavaScript array of objects. This allows you to operate on the documents as you would a normal set of JavaScript objects.

Lines 11–18 also use the find() method; however, the each() method is used to iterate through the Cursor object one document at a time. For each iteration, a single document is retrieved from MongoDB and passed in as the second parameter to the callback function.

Lines 19–22 implement the findOne() method. Notice the simple query on the type field. The callback function receives the object and outputs it to the screen.

Listing 14.2 doc_find.js: Finding documents in a MongoDB collection

01 var MongoClient = require('mongodb').MongoClient;
02 MongoClient.connect("mongodb://localhost/", function(err, db) {
03   var myDB = db.db("astro");
04   myDB.collection("nebulae", function(err, nebulae){
05     nebulae.find(function(err, items){
06       items.toArray(function(err, itemArr){
07         console.log("Document Array: ");
08         console.log(itemArr);
09       });
10     });
11     nebulae.find(function(err, items){
12       items.each(function(err, item){
13         if(item){
14           console.log("Singular Document: ");
15           console.log(item);
16         }
17       });
18     });
19     nebulae.findOne({type:'planetary'}, function(err, item){
20       console.log("Found One: ");
21       console.log(item);
22     });
23   });
24 });

Listing 14.2 Output doc_find.js: Finding documents in a MongoDB collection

Document Array:
[ { _id: 598e04b98e397c0f8464bb99,
    ngc: 'NGC 7293',
    name: 'Helix',
    type: 'planetary',
    location: 'Aquila' },
  { _id: 598e04b98e397c0f8464bb9b,
    ngc: 'NGC 1952',
    name: 'Crab',
    type: 'supernova',
    location: 'Taurus' },
  { _id: 598e04b98e397c0f8464bb9a,
    ngc: 'NGC 6543',
    name: 'Cat's Eye',
    type: 'planetary',
    location: 'Draco' } ]
Singular Document:
{ _id: 598e04b98e397c0f8464bb99,
  ngc: 'NGC 7293',
  name: 'Helix',
  type: 'planetary',
  location: 'Aquila' }
Singular Document:
{ _id: 598e04b98e397c0f8464bb9b,
  ngc: 'NGC 1952',
  name: 'Crab',
  type: 'supernova',
  location: 'Taurus' }
Singular Document:
{ _id: 598e04b98e397c0f8464bb9a,
  ngc: 'NGC 6543',
  name: 'Cat's Eye',
  type: 'planetary',
  location: 'Draco' }
Found One:
{ _id: 598e04b98e397c0f8464bb99,
  ngc: 'NGC 7293',
  name: 'Helix',
  type: 'planetary',
  location: 'Aquila' }

Updating Documents in a Collection

Once objects have been inserted into a collection you often need to update them from time to time as the data changes. The MongoDB Node.js driver provides several methods for updating documents. The most commonly used is the update() method, which is versatile and easy to implement. The following shows the syntax for the update() method:

update(query, update, [options], [callback])

The query parameter is a document used to identify 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, and 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 14.2 lists the operators that can be used.

The options parameter specifies the database change options described previously in Table 14.1. The callback function is required if you are implementing a write concern in the options. The first parameter of the callback function is an error, and the second parameter is an array of the documents inserted into the collection.

When updating multiple documents with the update() call, you can isolate writes to protect the documents from other writes using the $isolate: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({type:"Planetary", $isolated:1}, {updated:true}, {multi:true})

Listing 14.3 illustrates updating multiple objects using the update() method. Lines 9–19 implement the update() method and callback to change the type planetary to Planetary and add a new field named updated. Notice that the $set operator is used to set values. Also notice that upsert is false so that new documents will not be created, multi is true so that multiple documents will get updated, and w is 1 so that the request will wait for the write operation before returning.

Listing 14.3 doc_update.js: Updating multiple documents in the database

01 var MongoClient = require('mongodb').MongoClient;
02 MongoClient.connect("mongodb://localhost/", function(err, db) {
03   var myDB = db.db("astro");
04   myDB.collection("nebulae", function(err, nebulae){
05     nebulae.find({type:"planetary"}, function(err, items){
06       items.toArray(function(err, itemArr){
07         console.log("Before Update: ");
08         console.log(itemArr);
09         nebulae.update({type:"planetary", $isolated:1},
10                        {$set:{type:"Planetary", updated:true}},
11                        {upsert:false, multi:true, w:1},
12                        function(err, results){
13           nebulae.find({type:"Planetary"}, function(err, items){
14             items.toArray(function(err, itemArr){
15               console.log("After Update: ");
16               console.log(itemArr);
17               db.close();
18             });
19           });
20         });
21       });
22     });
23   });
24 });

Listing 14.3 Output doc_update.js: Updating multiple documents in the database

Before Update:
[ { _id: 598e04b98e397c0f8464bb99,
    ngc: 'NGC 7293',
    name: 'Helix',
    type: 'planetary',
    location: 'Aquila' },
  { _id: 598e04b98e397c0f8464bb9a,
    ngc: 'NGC 6543',
    name: 'Cat's Eye',
    type: 'planetary',
    location: 'Draco' } ]
After Update:
[ { _id: 598e04b98e397c0f8464bb99,
    ngc: 'NGC 7293',
    name: 'Helix',
    type: 'Planetary',
    location: 'Aquila',
    updated: true },
  { _id: 598e04b98e397c0f8464bb9a,
    ngc: 'NGC 6543',
    name: 'Cat's Eye',
    type: 'Planetary',
    location: 'Draco',
    updated: true } ]

Atomically Modifying Documents in a Collection

The Collection object provides the findAndModify() function that performs an atomic write on a single document in the collection. This is useful if you need to ensure that no other processes can write to your document at the same time. The following shows the syntax for the findAndModify() method:

findAndModify(query, sort, update, [options], callback)

The query parameter is a document used to identify which document you want to modify. The request matches the properties and values in the query with the fields and values of the object, and only those matching the query are modified.

The sort parameter is an array of [field, sort_order] pairs that specify which fields to sort on when finding the item to modify. The sort_order value is 1 for ascending, -1 for descending. The update parameter is an object that specifies the changes to make to the documents that match the query. Table 14.2 lists the operators that can be used.

The options parameter specifies the database change options described previously in Table 14.1.The callback function is required if you are implementing a write concern in the options. The first parameter of the callback function is an error, and the second parameter is the object being modified. If new is set to true in the options, then the newly modified object is returned. If new is set to false, the pre-modified object is returned. Getting back the pre-modified object can be useful if you need to verify changes or store the original somewhere else.

Listing 14.4 illustrates performing an atomic write on a single object in the MongoDB database. Lines 9–15 implement the findAndModify() operation. Notice that the sort value is [['name', 1]], which means sort on name in ascending order. Also notice that w is 1 to enable the write concern, and new is set to true so that the modified object is returned in the callback function and displayed on the console.

Listing 14.4 doc_modify.js: Atomically modifying a document using findAndModify()

01 var MongoClient = require('mongodb').MongoClient;
02 MongoClient.connect("mongodb://localhost/", function(err, db) {
03   var myDB = db.db("astro");
04   myDB.collection("nebulae", function(err, nebulae){
05     nebulae.find({type:"supernova"}, function(err, items){
06       items.toArray(function(err, itemArr){
07         console.log("Before Modify: ");
08         console.log(itemArr);
09         nebulae.findAndModify({type:"supernova"}, [['name', 1]],
10             {$set: {type:"Super Nova", "updated":true}},
11             {w:1, new:true}, function(err, doc){
12           console.log("After Modify: ");
13           console.log(doc);
14           db.close();
15         });
16       });
17     });
18   });
19 });

Listing 14.4 Output doc_modify.js: Atomically modifying a document using findAndModify()

Before Modify:
[ { _id: 598e04b98e397c0f8464bb9b,
    ngc: 'NGC 1952',
    name: 'Crab',
    type: 'supernova',
    location: 'Taurus' } ]
After Modify:
{ lastErrorObject: { updatedExisting: true, n: 1 },
  value:
   { _id: 598e04b98e397c0f8464bb9b,
     ngc: 'NGC 1952',
     name: 'Crab',
     type: 'Super Nova',
     location: 'Taurus',
     updated: true },
  ok: 1 }

Saving Documents in a Collection

The save() method on Collection objects is interesting. It can be used to insert or update a document in the database. The save() method is not as efficient as insert() or update() but can be 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:

save(doc, [options], [callback])

The doc parameter is the document object you want to save to the collection. The options parameter specifies the database change options described previously in Table 14.1. The callback function is required if you are implementing a write concern in the options. The first parameter of the callback function is an error, and the second parameter is the object that was just saved to the collection.

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

Listing 14.5 illustrates retrieving an object from the database, modifying it, and saving it back to the database using the save() method. The save() method and callback are implemented in lines 9–15. Notice that the save() method is much simpler to use than the update() and findAndModify() methods. Also notice that the savedItem is returned to the callback function and displayed on the console.

Listing 14.5 doc_save.js: Updating and saving an existing document using save()

01 var MongoClient = require('mongodb').MongoClient;
02 MongoClient.connect("mongodb://localhost/", function(err, db) {
03   var myDB = db.db("astro");
04   myDB.collection("nebulae", function(err, nebulae){
05     nebulae.findOne({type:"supernova"}, function(err, item){
06       console.log("Before Save: ");
07       console.log(item);
08       item.info = "Some New Info";
09       nebulae.save(item, {w:1}, function(err, results){
10         nebulae.findOne({_id:item._id}, function(err, savedItem){
11           console.log("After Save: ");
12           console.log(savedItem);
13           db.close();
14         });
15       });
16     });
17   });
18 });

Listing 14.5 Output doc_save.js: Updating and saving an existing document using save()

Before Save:
{ _id: 598e06c4efe25f1c0cf4932e,
  ngc: 'NGC 1952',
  name: 'Crab',
  type: 'supernova',
  location: 'Taurus' }
After Save:
{ _id: 598e06c4efe25f1c0cf4932e,
  ngc: 'NGC 1952',
  name: 'Crab',
  type: 'supernova',
  location: 'Taurus',
  info: 'Some New Info' }

Upserting Documents in Collection

Another type of update that you can perform on documents is the upsert, which is the combination of updating the object if it exists or 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, a normal update() is much more efficient, as is an insert() if you know the document does not already exist.

To implement an upsert, all you need to do is include the upsert:true option in the update() method’s options object. This tells the request to try to update the object if it exists; otherwise, the object specified will be inserted.

Listing 14.6 illustrates using upsert with the update() method. The update() in lines 9–12 creates the object because it does not exist. Then in line 18 the _id value of the inserted document is retrieved and used in the query of the update() in lines 19–22 to ensure an existing document will be found and updated. Notice that initially there are no documents matching the descriptor, and then after the first update the document is inserted and then modified after the second update.

Listing 14.6 doc_upsert.js: Using upsert to insert new documents or update existing ones

01 var MongoClient = require('mongodb').MongoClient;
02 MongoClient.connect("mongodb://localhost/", function(err, db) {
03   var myDB = db.db("astro");
04   myDB.collection("nebulae", function(err, nebulae){
05     nebulae.find({type:"diffuse"}, function(err, items){
06       items.toArray(function(err, itemArr){
07         console.log("Before Upsert: ");
08         console.log(itemArr);
09         nebulae.update({type:"diffuse"},
10             {$set: {ngc:"NGC 3372", name:"Carina",
11                     type:"diffuse",location:"Carina"}},
12             {upsert:true, w:1,forceServerObjectId:false},
13             function(err, results){
14           nebulae.find({type:"diffuse"}, function(err, items){
15             items.toArray(function(err, itemArr){
16               console.log("After Upsert 1: ");
17               console.log(itemArr);
18               var itemID = itemArr[0]._id;
19               nebulae.update({_id:itemID},
20                   {$set: {ngc:"NGC 3372", name:"Carina",
21                           type:"Diffuse",location:"Carina"}},
22                   {upsert:true, w:1}, function(err, results){
23                 nebulae.findOne({_id:itemID}, function(err, item){
24                   console.log("After Upsert 2: ");
25                   console.log(item);
26                   db.close();
27                 });
28               });
29             });
30           });
31         });
32       });
33     });
34   });
35 });

Listing 14.6 Output doc_upsert.js: Using upsert to insert new documents or update existing ones

Before Upsert:
[]
After Upsert 1:
[ { _id: 598e070aac7bf01c2a209601,
    type: 'diffuse',
    ngc: 'NGC 3372',
    name: 'Carina',
    location: 'Carina' } ]
After Upsert 2:
{ _id: 598e070aac7bf01c2a209601,
  type: 'Diffuse',
  ngc: 'NGC 3372',
  name: 'Carina',
  location: 'Carina' }

Deleting Documents from a Collection

At times, you 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 it simple to delete documents from a collection. The syntax for the remove() method is shown here:

remove([query], [options], [callback])

The query parameter is a document used to identify 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, and only those matching the query are deleted. If no query is provided, all the documents in the collection are deleted.

The options parameter specifies the database change options described previously in Table 14.1. The callback function is required if you are implementing a write concern in the options. The first parameter of the callback function is an error, and the second parameter is a count of the documents deleted.

Listing 14.7 illustrates using the remove() method to delete objects from the collection. The remove() and callback implemented in lines 9–18 query the collection for documents that have type planetary and delete them from the collection. Notice that the results parameter of the callback is the count of documents deleted. Listing 14.7 Output shows the output of Listing 14.7 with the before delete and after delete documents in the collection.

Listing 14.7 doc_delete.js: Deleting documents from a collection

01 var MongoClient = require('mongodb').MongoClient;
02 MongoClient.connect("mongodb://localhost/", function(err, db) {
03   var myDB = db.db("astro");
04   myDB.collection("nebulae", function(err, nebulae){
05     nebulae.find(function(err, items){
06       items.toArray(function(err, itemArr){
07         console.log("Before Delete: ");
08         console.log(itemArr);
09         nebulae.remove({type:"planetary"}, function(err, results){
10           console.log("Deleted " + results + " documents.");
11           nebulae.find(function(err, items){
12             items.toArray(function(err, itemArr){
13               console.log("After Delete: ");
14               console.log(itemArr);
15               db.close();
16             });
17           });
18         });
19       });
20     });
21   });
22 });

Listing 14.7 Output doc_delete.js: Deleting documents from a collection

Before Delete:
[ { _id: 598e06c4efe25f1c0cf4932c,
    ngc: 'NGC 7293',
    name: 'Helix',
    type: 'planetary',
    location: 'Aquila' },
  { _id: 598e06c4efe25f1c0cf4932d,
    ngc: 'NGC 6543',
    name: 'Cat's Eye',
    type: 'planetary',
    location: 'Draco' },
  { _id: 598e06c4efe25f1c0cf4932e,
    ngc: 'NGC 1952',
    name: 'Crab',
    type: 'supernova',
    location: 'Taurus',
    info: 'Some New Info' },
  { _id: 598e070aac7bf01c2a209601,
    type: 'Diffuse',
    ngc: 'NGC 3372',
    name: 'Carina',
    location: 'Carina' } ]
Delete:
 {"n":0,"ok":1}
After Delete:
[ { _id: 598e06c4efe25f1c0cf4932c,
    ngc: 'NGC 7293',
    name: 'Helix',
    type: 'planetary',
    location: 'Aquila' },
  { _id: 598e06c4efe25f1c0cf4932d,
    ngc: 'NGC 6543',
    name: 'Cat's Eye',
    type: 'planetary',
    location: 'Draco' },
  { _id: 598e06c4efe25f1c0cf4932e,
    ngc: 'NGC 1952',
    name: 'Crab',
    type: 'supernova',
    location: 'Taurus',
    info: 'Some New Info' },
  { _id: 598e070aac7bf01c2a209601,
    type: 'Diffuse',
    ngc: 'NGC 3372',
    name: 'Carina',
    location: 'Carina' } ]

Removing a Single Document from a Collection

You can also delete documents from the database using the findAndRemove() method. This is similar to the findAndModify() method in its syntax and application. The following shows the syntax for the findAndRemove() method:

findAndRemove(query, sort, [options], callback)

The query parameter is a document used to identify which document you want to remove. The request matches the properties and values in the query with the fields and values of the object, and only those matching the query are removed.

The sort parameter is an array of [field, sort_order] pairs that specify which fields to sort on when finding the item to remove. The sort_order is a value of 1 for ascending and -1 for descending. The options parameter specifies the database change options described previously in Table 14.1. The first parameter of the callback function is an error, and the second parameter is the results of the document deletion.

Listing 14.8 illustrates deleting a document using the findAndRemove() method. The findAndRemove() and callback are implemented in lines 9–18. The items of type planetary are searched on. The sort order [['name', 1]] specifies to sort the items by name in ascending order. Listing 14.8 Output shows that the Cat's Eye entry was deleted and not the Helix because of the sort order.

Listing 14.8 doc_delete_one.js: Deleting single documents using findAndRemove()

01 var MongoClient = require('mongodb').MongoClient;
02 MongoClient.connect("mongodb://localhost/", function(err, db) {
03   var myDB = db.db("astro");
04   myDB.collection("nebulae", function(err, nebulae){
05     nebulae.find(function(err, items){
06       items.toArray(function(err, itemArr){
07         console.log("Before Delete: ");
08         console.log(itemArr);
09         nebulae.findAndRemove({type:"planetary"}, [['name', 1]],
10                               {w:1}, function(err, results){
11           console.log("Deleted " + results + " documents.");
12           nebulae.find(function(err, items){
13             items.toArray(function(err, itemArr){
14               console.log("After Delete: ");
15               console.log(itemArr);
16               db.close();
17             });
18           });
19         });
20       });
21     });
22   });
23 });

Listing 14.8 Output doc_delete_one.js: Deleting single documents using findAndRemove()

Before Delete:
[ { _id: 598e06c4efe25f1c0cf4932c,
    ngc: 'NGC 7293',
    name: 'Helix',
    type: 'planetary',
    location: 'Aquila' },
  { _id: 598e06c4efe25f1c0cf4932d,
    ngc: 'NGC 6543',
    name: 'Cat's Eye',
    type: 'planetary',
    location: 'Draco' },
  { _id: 598e06c4efe25f1c0cf4932e,
    ngc: 'NGC 1952',
    name: 'Crab',
    type: 'supernova',
    location: 'Taurus',
    info: 'Some New Info' },
  { _id: 598e070aac7bf01c2a209601,
    type: 'Diffuse',
    ngc: 'NGC 3372',
    name: 'Carina',
    location: 'Carina' } ]
Deleted [object Object] documents.
After Delete:
[ { _id: 598e06c4efe25f1c0cf4932c,
    ngc: 'NGC 7293',
    name: 'Helix',
    type: 'planetary',
    location: 'Aquila' },
  { _id: 598e06c4efe25f1c0cf4932e,
    ngc: 'NGC 1952',
    name: 'Crab',
    type: 'supernova',
    location: 'Taurus',
    info: 'Some New Info' },
  { _id: 598e070aac7bf01c2a209601,
    type: 'Diffuse',
    ngc: 'NGC 3372',
    name: 'Carina',
    location: 'Carina' } ]

Summary

The MongoDB Node.js driver provides several methods to insert, access, modify, and remove documents from collections. insert(), save(), and even update() with upsert can be used to insert documents into the database. The update(), save(), and findAndModify() methods can be used to update existing documents. The remove() and findAndRemove() methods can be used to delete documents.

The methods used to update documents in the database include options that allow you to define the write concern, journaling, and other settings that control the behavior of the write request and response. Also the update structure that MongoDB uses to update documents is much easier to implement and maintain than the long, complex query strings you may have seen in SQL.

Next

Chapter 15 expands on the concept of finding objects in the database. This chapter introduced you to find() and findOne(), but Chapter 15 includes more complex examples of how to filter, sort, and limit the results returned when finding objects in a collection.

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

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