Errata

MongoDB: The Definitive Guide

Errata for MongoDB: The Definitive Guide

Submit your own errata for this product.

The errata list is a list of errors and their corrections that were found after the product was released. If the error was corrected in a later version or reprint the date of the correction will be displayed in the column titled "Date Corrected".

The following errata were submitted by our customers and approved as valid errors by the author or editor.

Color key: Serious technical mistake Minor technical mistake Language or formatting error Typo Question Note Update

Version Location Description Submitted By Date submitted Date corrected
Mobi
Page Location 563
Location 563

Or if you?re on Windows, run this: $ mongod.exe

Obviously the $ is UNIX not windows

Note from the Author or Editor:
Good point, it should be:

> mongod.exe

Ninja Assassin  Jun 03, 2013  Jun 06, 2014
PDF
Page Page 63
2nd paragraph

"the document is returned because 25 matches the first clause (it is greater than 25)"
should be changed to
"the document is returned because 25 matches the first clause (it is greater than 10)"

Johan Roch  Dec 08, 2013  Jun 06, 2014
PDF
Page 29,30
3rd paragraph

On Chapter 3

"Batch Insert"
I think it should be "Bulk Insert"

and Code:
> db.foo.batchInsert([{"_id" : 0}, {"_id" : 1}, {"_id" : 2}])
Wed May 22 12:20:40.234 JavaScript execution failed: TypeError: Property 'batchInsert' of object test.foo is not a function
> db.foo.batchinsert([{"_id" : 0}, {"_id" : 1}, {"_id" : 2}])
Wed May 22 12:21:08.443 JavaScript execution failed: TypeError: Property 'batchinsert' of object test.foo is not a function


I think It should be! "db.foo.insert"

> db.foo.insert([{"_id" : 0}, {"_id" : 1}, {"_id" : 2}])
>



Note from the Author or Editor:
It is called "batch insert," however you are correct about the function name. It should be:

> db.foo.insert([{"_id" : 0}, {"_id" : 1}, {"_id" : 2}])

Surachart Opun  May 21, 2013  Jun 06, 2014
Printed
Page 29
Batch Insert

According to http://docs.mongodb.org/manual/core/write-operations/ "batch insert" is now known as "bulk insert".

The final paragraph on page 29 should read something like: "You can try this out using the insert function, which since release 2.2 has optionally taken an array of documents to bulk insert."

Note from the Author or Editor:
Hmm, the drivers still use batch insert so it's probably still worth a mention, but this should probably be retitled Bulk Insert.

Simon Dismore  Jun 09, 2013  Jun 06, 2014
PDF
Page 30
2nd--to-last paragraph

"it check's the" → "it checks the"

Karl Broman  Jun 20, 2015 
PDF
Page 31
last paragraph

Code : > var timeRemoves = function() {

Please help check.
It should be
> db.tester.findOne();


Tested:
> db.findOne();
Wed May 22 12:44:59.420 JavaScript execution failed: TypeError: Property 'findOne' of object test is not a function
> db.tester.findOne();
{
"_id" : ObjectId("519c5a2b96aa44edfb12e196"),
"foo" : "bar",
"baz" : 456255,
"z" : -456245
}
>

Note from the Author or Editor:
... db.findOne(); // makes sure the remove finishes before continuing
should be:
... db.tester.findOne(); // makes sure the remove finishes before continuing

Surachart Opun  May 21, 2013  Jun 06, 2014
PDF
Page 39
2rd paragraph

The follow code isn't correct

db.movies.find({"genre" : "horror"},
... {"$push" : {"top10" : {
... "$each" : [{"name" : "Nightmare on Elm Street", "rating" : 6.6},
... {"name" : "Saw", "rating" : 4.3}],
... "$slice" : -10,
... "$sort" : {"rating" : -1}}}})

The correct code is

db.movies.update({"genre" : "horror"},
{"$push" : {"top10" : {
"$each" : [{"name" : "Nightmare on Elm Street", "rating" : 6.6},
{"name" : "Saw", "rating" : 4.3}],
"$slice" : -10,
"$sort" : {"rating" : -1}}}})

With "update" instead "find"

Barno  Aug 26, 2014 
Printed, PDF, ePub, Mobi, , Other Digital Version
Page 42
Code samples

db.blog.update should be db.blog.posts.update in both examples.

Kristina Chodorow
Kristina Chodorow
 
Aug 29, 2014 
PDF
Page 44
3rd paragraph

You suggest replacing the "$inc" function with a "$push" in an update.

However when I use the "$push" I get the following:

> var timeInc = function() {
... var start = (new Date()).getTime();
...
... for (var i=0; i<100000; i++) {
... db.tester.update({}, {"$push" : {"x" : 1}});
... db.getLastError();
... }
...
... var timeDiff = (new Date()).getTime() - start;
... print("Updates took: " + timeDiff + "ms");
... }
> timeInc()
Updates took: 147255ms
Cannot apply $push/$pushAll modifier to non-array
> db.tester.find()
{ "_id" : ObjectId("52aaa4daaf47dcd9bc8e573f"), "x" : 1 }

Can you please explain why I did not get the same results as when using the "$inc"?

Also, what is meant by " Cannot apply $push/$pushAll modifier to non-array"?

Note from the Author or Editor:
You must remove the document from the "tester" collection before running the $push example. Otherwise, you're trying to $push a value onto an integer and $pushing only works with arrays.

The text should mention that the collection should be dropped between the two runs (and should specify that it's an upsert, not an update).

Change the update call to this:
should be:
Remove the document and change the update call to this:

Anonymous  Dec 13, 2013  Jun 06, 2014
PDF
Page 44
3rd paragraph

How can the $push command be used to increment an integer number like the $inc?

> db.tester.remove()
> db.tester.update({}, {"$push" : {x : 1}})
> db.tester.find()
> db.tester.insert({x : [1]});
> db.tester.find()
{ "_id" : ObjectId("52b02cded47ab1c03e25b3e6"), "x" : [ 1 ] }
> db.tester.update({}, {"$push" : {x : 1}})
> db.tester.find()
{ "_id" : ObjectId("52b02cded47ab1c03e25b3e6"), "x" : [ 1, 1 ] }

The upsert will not work, the tester collection must already exist with an array of integer. Then using the $push command as you suggest would create an array of "1's" of size 100001, not an array of size "1" with a value of 100001. Would that not be correct? If I am in error would greatly appreciate you pointing out where I have gone wrong.

Could you please publish the code you used on your MacBook Air.

Note from the Author or Editor:
You cannot use $push to increment. The end result of 10000 $pushes should be an array with 100001 1s in it.

The first update should be an upsert.

db.tester.update({}, {"$inc" : {"x" : 1}});
should be:
db.tester.update({}, {"$inc" : {"x" : 1}}, {upsert : true});

Anonymous  Dec 17, 2013  Jun 06, 2014
PDF
Page 49
2nd paragraph

There's a missing closing bracket in the findAndModify example:

"update" : {"$set" : {"status" : "RUNNING"}})
should be
"update" : {"$set" : {"status" : "RUNNING"}}})

Note from the Author or Editor:
You are correct, thanks for catching that!

Giorgio Donnini  Jun 03, 2013  Jun 06, 2014
Printed
Page 70
Paginating results without skip

In this paragraph a workaround is presented how to
avoid using large skips as they are usually slow. But I think
this workaround only works if the values of "date" are unique
in the collection. Suppose the collection is sorted by date descending.
Suppose that in this sorted collection, the documents between
No 95 and No 105 have the same values for date. Then this
workaround will not work. The 2nd page will actually return the
documents from No 106 on which is not the desired behavior.




Note from the Author or Editor:
If the field is not unique, the client could be modified to track of the _id of the last date on the previous page.

Peter Petrov  Feb 15, 2014  Jun 06, 2014
Printed
Page 70
Paginating results without skip

In this example there, actually this part:
var page2 = db.foo.find({"date" : {"$gt" : latest.date}});
should be:
var page2 = db.foo.find({"date" : {"$lt" : latest.date}});
because the whole example is talking about retrieving and
displaying documents in descending order based on "date".
So for the second page, we should use "$lt", and not "$gt".



Peter Petrov  Feb 19, 2014  Jun 06, 2014
PDF
Page 71
3rd code example

Regarding finding a random document in a collection, this line is incorrect:
result = db.foo.findOne({"random" : {"$lt" : random}})

The author is using it guard against the case where the random number is bigger than the largest random key of documents in the collection. However, it will also fail to match (return null) if the only documents in the collection have random key values equal to the random number in the search criteria.

The solution is the use "$lte" instead of "$lt".

JeremyBower  May 10, 2013  Jun 06, 2014
Printed
Page 72
$maxscan paragraph

"This can be useful if you want a query to not to take too long..."
The "to not to take too long" part sounds like a typo.
I guess it should be "to not take too long" or "not to take too long".

Note from the Author or Editor:
Change "to not to take too long" to "to not take too long".

Peter Petrov  Feb 17, 2014  Jun 06, 2014
Printed
Page 72
$maxscan code example

This code fragment
db.foo.find(criteria)._addSpecial("$maxscan", 20)
should actually read
db.foo.find(criteria)._addSpecial("$maxScan", 20)
because $maxscan does not seem to work i.e.
it does not limit anything. $maxScan does.
It is case-sensitive.







Note from the Author or Editor:
Change both instances of $maxscan to $maxScan.

Peter Petrov  Feb 26, 2014  Jun 06, 2014
Printed
Page 75
runCommand example

There's this text on page 76:

"A database command always returns a document containing the key "ok". If "ok"is 1, the command was successful; and if it is 0, the command failed for some reason."

But the code examples on pages 75-77 are not consistent with respect to the ok values. Some show true/false, some show 1/0.

Note from the Author or Editor:
This should be changed to say that ok always indicates success or failure, either with true/false or 1/0.

change "If "ok" is 1, the command was successful; and if it is 0, the command failed for some reason." to "If "ok" is a true value (1, 1.0, or true)
then the command was successful. If it is false then the command failed for some reason."

Peter Petrov  Feb 26, 2014  Jun 06, 2014
Printed
Page 83
last paragraph

"However, indexes have their price: every write (insert, update, or delete) will take longer for every index you add."

Actually for updates isn't it true that it has an additional price only if the update updates a field which is part of the keys of some index? I think it is so but I am not 100% sure. I don't see why updating a field which is part of none of the indexes will have an additional price (price for reorganizing some of the indexes).

Note from the Author or Editor:
It depends. If the update makes the document bigger and it has to be moved, then all of the indexes must be updated. But in other cases you are correct. This should be clarified.

However, indexes have their price: every write (insert, update, or delete) will take longer for every Introduction to index you add"
should be:
"However, indexes have their price: every write that touches an indexed field (insert, update, or delete) will take longer for every index you add"

Peter Petrov  Mar 10, 2014  Jun 06, 2014
PDF
Page 94
First paragraph below "OR queries" heading

Typo:

This only exception to this rule is "$or".

Should be

The only exception to this rule is "$or".

JeremyBower  May 10, 2013  Jun 06, 2014
Printed
Page 94
last textual (non-code) paragraph

"This only exception to this rule is"

I think this should read:

"The only exception to this rule is"

This is just a very minor thing though.

Peter Petrov  Mar 10, 2014  Jun 06, 2014
PDF
Page 95
3rd paragraph

This paragraph has incorrect find statements:

When running "$in" queries there is no way, other than sorting, to control the order of documents returned. For example, {"x" : [1, 2, 3]} will return documents in the same order as {"x" : [3, 2, 1]}.

It's missing the $in operator. It should be:

When running "$in" queries there is no way, other than sorting, to control the order of documents returned. For example, {"x" : {$in, [1, 2, 3]}} will return documents in the same order as {"x" : {$in, [3, 2, 1]}}.

Note from the Author or Editor:
Almost, it should be:

For example, {"x" : {"$in" : [1, 2, 3]}} will return documents in the same order as {"x" : {"$in" : [3, 2, 1]}}.

JeremyBower  May 10, 2013  Jun 06, 2014
Printed
Page 98
the paragraph before the last one

The most basic type of explain() is on a query that doesn?t use an index. You can tell
that a query doesn?t use an index because it uses a "BasicCursor". Conversely, most queries that use an index use a BtreeCursor (some special types of indexes, such as geospatial indexes, use their own type of cursor).

I wonder why "BasicCursor" is in parentheses and BtreeCursor is not. I think either both should be with or without parentheses. I realize this is very minor though.

Note from the Author or Editor:
Put quotes around BtreeCursor.

Peter Petrov  Mar 25, 2014  Jun 06, 2014
Printed
Page 100
nscannedObjects paragraph

"This is a count of the number of times MongoDB had to follow an index pointer to the actual document on disk"

Not fully sure but ... "a count of the number of times" sounds like a tautology to me.

Note from the Author or Editor:
change to "This is the number of times MongoDB had to"

Peter Petrov  Mar 25, 2014  Jun 06, 2014
Printed
Page 106
code below 3rd paragraph

Collection name is missing in the code:

> db.ensureIndex( ...

should be, for example:

> db.users.ensureIndex( ...

Note from the Author or Editor:
Whoops.

Simon Dismore  Jun 09, 2013  Jun 06, 2014
Printed
Page 110
Figure 6-2

Figure 6-2 is inconsistent with Figure 6-1. In 6-1 the left-hand snowflake is older than the right-hand-snowflake, so in 6-2 the left-hand snowflake should be replaced by the new document.

Note from the Author or Editor:
I think the illustrators must have translated it incorrectly from the original. You're actually the first one to notice in two editions!

Simon Dismore  Jun 09, 2013  Jun 06, 2014
Printed, PDF
Page 114
last line on page, code


db.foo.ensureIndex({"lastUpdated" : 1}, {"expireAfterSecs" : 60*60*24})

should be...

db.foo.ensureIndex({"lastUpdated" : 1}, {"expireAfterSeconds" : 60*60*24})


The error occurs in the code on page 115 also.

David Alexis  Feb 17, 2014  Jun 06, 2014
Printed
Page 114
No-_id collections

"However, you can create collections with "_id" indexes by setting the autoIndexId option to false when calling createCollection."

I think it should read:

"However, you can create collections without "_id" indexes by setting the autoIndexId option to false when calling createCollection."

Peter Petrov  Mar 25, 2014  Jun 06, 2014
Printed
Page 114
TTL Indexes

"If you need a more flexible age-out system, time-to-live (TTL) indexes allow you to set a timeout for each document."

I think this ("for each document") somehow implies that the timeout value is per document while actually it seems to be per index, the expireAfterSecs value is one per index, not one per document. I mean, we cannot set different expireAfterSecs on each document.

Note from the Author or Editor:
What I was trying to say was that documents do not have an implicit timestamp. You create a TTL index on a field, but you can give the documents any value you want for that field (or none at all) so every document can live for a different length of time.

Perhaps this could be phrased better.

Peter Petrov  Mar 26, 2014  Jun 06, 2014
Printed
Page 115
example after 3rd paragraph

db.runCommand({"collMod" : "someapp.cache", "expireAfterSecs" : 3600})

I think this is an incorrect syntax. The correct one seems to be:

db.runCommand( {"collMod" : "someapp.cache" , "index" : { "keyPattern" : {"lastUpdated" : 1} , "expireAfterSeconds" : 3600 } } );

Pages 114 and 115 talk about TTL indexes, not about TTL collections. I am not sure actually if there're TTL collections or not. But the command in the book apparently doesn't modify an index, it modifies a collection (if its syntax is allowed at all).

This is very confusing.

If I run the original command, I get these errors.

> db.runCommand({"collMod" : "test_ttl", "expireAfterSeconds" : 3600})
{ "ok" : 0, "errmsg" : "unknown option to collMod: expireAfterSeconds" }
> db.runCommand({"collMod" : "test_ttl", "expireAfterSecs" : 3600})
{ "ok" : 0, "errmsg" : "unknown option to collMod: expireAfterSecs" }

Note from the Author or Editor:
I think that this changed since the book was written. See http://docs.mongodb.org/manual/reference/command/collMod/#index for the correct format.

Change db.runCommand({"collMod" : "someapp.cache", "expireAfterSecs" : 3600}) to their suggestion:
db.runCommand( {"collMod" : "someapp.cache" , "index" : { "keyPattern" : {"lastUpdated" : 1} , "expireAfterSeconds" : 3600 } } );

Peter Petrov  Mar 26, 2014  Jun 06, 2014
Printed
Page 119
paragraph 6

"You cannot use a multikey field for any of the prefix or postfix index fields."

I tested this by creating a collection which has these fields:
"dt" : some integers here in the different docs (one integer per doc)
"txt" : some texts here (one text/string per doc)
"author" : some texts/strings, one per doc (but also an array of integers in just one of the documents)

Then I am able to do

db.blog.ensureIndex({"dt" : 1, "txt" : "text", "author" : 1});

contrary to what the book says. I mean, "author" is a postfix field here,
it is multikey (as it contains an array), but I can still create this index.

Seems either I am missing something, or maybe something has
changed since the book was written. I am testing this on version 2.4.8.


Note from the Author or Editor:
Remove the sentence "You cannot use a multikey field for any of the prefix or postfix index fields."

Peter Petrov  Apr 01, 2014  Jun 06, 2014
Printed
Page 125
"files_id" description

"The "_id" of the file document that contains the metadata for this chunk."

Not fully sure as it's just a language remark... but this sounds like "the chunk's metadata", and not like "that's the metadata of the whole file" (while actually the latter is true, I think; this becomes clear from the next page).

Note from the Author or Editor:
"The "_id" of the file document that contains the metadata for this chunk" should be changed to "The "_id" of the file document that contains the metadata for the file this chunk is from."

Peter Petrov  Apr 01, 2014  Jun 06, 2014
Printed
Page 126
3rd paragraph from the bottom up

"You might want to keep information such as download count, mimetype, or user rating with a file's metadata."

"mimetype" - I think it should be spelled as "mime type" or even better as "MIME type".

Peter Petrov  Apr 01, 2014  Jun 06, 2014
Printed
Page 127
last paragraph

I think this:

"maps to a aggregation framework operator"

should read:

"maps to an aggregation framework operator"


Peter Petrov  May 04, 2014  Jun 06, 2014
Printed
Page 132
Date expressions paragraph

"This would calculate many years"

I think this should read

"This would calculate how many years"

Peter Petrov  Apr 29, 2014  Jun 06, 2014
Printed
Page 132
Date expressions paragraph

"Each of these date types is basically the same"

I don't think these are date types, I think they are "date operations"
or "date operators" but date types definitely sounds incorrect to me.

Note from the Author or Editor:
Change to "date operators"

Peter Petrov  May 04, 2014  Jun 06, 2014
Printed
Page 134
Right before "A projection example"

"you can use this conditionals to detect missing values and pop&#8208;
ulate them"

I think this should read:

"you can use these conditionals to detect missing values and pop&#8208;
ulate them"

Peter Petrov  Apr 29, 2014  Jun 06, 2014
Printed
Page 135
first paragraph, second bullet

"and we wanted to organize student into groups"

I think it should read

"and we wanted to organize the students into groups"

Peter Petrov  May 04, 2014  Jun 06, 2014
Printed
Page 135
Arithmetic operators paragraph

There are two operators that can be used to compute numeric val&#8208;
ues from fields: "$sum"and "$average".

Here this "$average" should read "$avg".

On the next page 136, it is correctly written as "$avg".

Peter Petrov  May 04, 2014  Jun 06, 2014
PDF
Page 136
$avg example

$average should be $avg.

Kristina Chodorow
Kristina Chodorow
 
Sep 27, 2013  Jun 06, 2014
Printed
Page 136
$avg example

> db.sales.aggregate(
... {
... "$group" : {
... "_id" : "$country",
... "totalRevenue" : {"$average" : "$revenue"},
... "numSales" : {"$sum" : 1}
... }
... })


I think "totalRevenue" should read "averageRevenue".
That makes more sense.

Peter Petrov  Apr 09, 2014  Jun 06, 2014
Printed
Page 138
$unwind example

In the output from $unwind,
I think that "results" should read "result"
(unless it was otherwise in previous versions of
MongoDB; I tested it in version 2.4.8).

Peter Petrov  May 06, 2014  Jun 06, 2014
PDF
Page 161
Last paragraph, first sentence

This sentence has a typo:
"If your document has one field that grows, try to keep is as the last field in the document (but before "garbage")."

"try to keep is" -> "try to keep it"

JeremyBower  May 10, 2013  Jun 06, 2014
Printed, PDF, ePub, Mobi,
Page 379
2nd paragraph

The closing paren is 4 words late.

Kristina Chodorow
Kristina Chodorow
 
Jul 08, 2013  Jun 06, 2014