Regular expression flags (for example, i) are allowed but not required. If we want to
match not only various capitalizations of joe, but also joey, we can continue to improve
our regular expression:
> db.users.find({"name" : /joey?/i})
MongoDB uses the Perl Compatible Regular Expression (PCRE) library to match reg‐
ular expressions; any regular expression syntax allowed by PCRE is allowed in
MongoDB. It is a good idea to check your syntax with the JavaScript shell before using
it in a query to make sure it matches what you think it matches.
MongoDB can leverage an index for queries on prefix regular expres‐
sions (e.g., /^joey/). Indexes cannot be used for case-insensitive
searches (/^joey/i).
Regular expressions can also match themselves. Very few people insert regular expres‐
sions into the database, but if you insert one, you can match it with itself:
> db.foo.insert({"bar" : /baz/})
> db.foo.find({"bar" : /baz/})
{
"_id" : ObjectId("4b23c3ca7525f35f94b60a2d"),
"bar" : /baz/
}
Querying Arrays
Querying for elements of an array is designed to behave the way querying for scalars
does. For example, if the array is a list of fruits, like this:
> db.food.insert({"fruit" : ["apple""banana""peach"]})
the following query:
> db.food.find({"fruit" : "banana"})
will successfully match the document. We can query for it in much the same way as we
would if we had a document that looked like the (illegal) document: {"fruit" : "ap
ple", "fruit" : "banana", "fruit" : "peach"}.
$all
If you need to match arrays by more than one element, you can use "$all". This allows
you to match a list of elements. For example, suppose we created a collection with three
elements:
> db.food.insert({"_id" : 1"fruit" : ["apple""banana""peach"]})
> db.food.insert({"_id" : 2"fruit" : ["apple""kumquat""orange"]})
> db.food.insert({"_id" : 3"fruit" : ["cherry""banana""apple"]})
Type-Specific Queries | 59
Asp.net merge pdf files - Merge, append PDF files in C#.net, ASP.NET, MVC, Ajax, WinForms, WPF
Provide C# Demo Codes for Merging and Appending PDF Document
pdf mail merge plug in; acrobat split pdf into multiple files
Asp.net merge pdf files - VB.NET PDF File Merge Library: Merge, append PDF files in vb.net, ASP.NET, MVC, Ajax, WinForms, WPF
VB.NET Guide and Sample Codes to Merge PDF Documents in .NET Project
add multiple pdf files into one online; break a pdf into multiple files
Then we can find all documents with both "apple" and "banana" elements by querying
with "$all":
> db.food.find({fruit : {$all : ["apple""banana"]}})
{"_id" : 1"fruit" : ["apple", "banana""peach"]}
{"_id" : 3"fruit" : ["cherry", "banana", "apple"]}
Order does not matter. Notice "banana" comes before "apple" in the second result.
Using a one-element array with "$all" is equivalent to not using "$all". For instance,
{fruit : {$all : ['apple']} will match the same documents as {fruit : 'apple'}.
You can also query by exact match using the entire array. However, exact match will not
match a document if any elements are missing or superfluous. For example, this will
match the first document above:
> db.food.find({"fruit" : ["apple""banana""peach"]})
But this will not:
> db.food.find({"fruit" : ["apple""banana"]})
and neither will this:
> db.food.find({"fruit" : ["banana""apple""peach"]})
If you want to query for a specific element of an array, you can specify an index using
the syntax key.index:
> db.food.find({"fruit.2" : "peach"})
Arrays are always 0-indexed, so this would match the third array element against the
string "peach".
$size
A useful conditional for querying arrays is "$size", which allows you to query for arrays
of a given size. Here’s an example:
> db.food.find({"fruit" : {"$size" : 3}})
One common query is to get a range of sizes. "$size" cannot be combined with another
$ conditional (in this example, "$gt"), but this query can be accomplished by adding a
"size" key to the document. Then, every time you add an element to the array, incre‐
ment the value of "size". If the original update looked like this:
> db.food.update(criteria, {"$push" : {"fruit" : "strawberry"}})
it can simply be changed to this:
> db.food.update(criteria
... {"$push" : {"fruit" : "strawberry"}, "$inc" : {"size" : 1}})
Incrementing is extremely fast, so any performance penalty is negligible. Storing docu‐
ments like this allows you to do queries such as this:
60 | Chapter 4: Querying
VB.NET PDF- HTML5 PDF Viewer for VB.NET Project
PDF; Merge PDF Files; Split PDF Document; Remove Password from PDF; Change PDF Permission Settings. FREE TRIAL: HOW TO: XDoc.HTML5 Viewer for C#▶: C# ASP.NET:
pdf combine files online; combine pdf online
Online Merge PDF files. Best free online merge PDF tool.
Thus, C#.NET PDF document merge library control can Download and try RasterEdge.XDoc. PDF for .NET and imaging solutions, available for ASP.NET AJAX, Silverlight
split pdf into multiple files; combine pdf files
> db.food.find({"size" : {"$gt" : 3}})
Unfortunately, this technique doesn’t work as well with the "$addToSet" operator.
The $slice operator
As mentioned earlier in this chapter, the optional second argument to find specifies the
keys to be returned. The special "$slice" operator can be used to return a subset of
elements for an array key.
For example, suppose we had a blog post document and we wanted to return the first
10 comments:
> db.blog.posts.findOne(criteria, {"comments" : {"$slice" : 10}})
Alternatively, if we wanted the last 10 comments, we could use −10:
> db.blog.posts.findOne(criteria, {"comments" : {"$slice" : -10}})
"$slice" can also return pages in the middle of the results by taking an offset and the
number of elements to return:
> db.blog.posts.findOne(criteria, {"comments" : {"$slice" : [2310]}})
This would skip the first 23 elements and return the 24th through 33th. If there were
fewer than 33 elements in the array, it would return as many as possible.
Unless otherwise specified, all keys in a document are returned when "$slice" is used.
This is unlike the other key specifiers, which suppress unmentioned keys from being
returned. For instance, if we had a blog post document that looked like this:
{
"_id" : ObjectId("4b2d75476cc613d5ee930164"),
"title" : "A blog post",
"content" : "...",
"comments" : [
{
"name" : "joe",
"email" : "joe@example.com",
"content" : "nice post."
},
{
"name" : "bob",
"email" : "bob@example.com",
"content" : "good post."
}
]
}
and we did a "$slice" to get the last comment, we’d get this:
> db.blog.posts.findOne(criteria, {"comments" : {"$slice" : -1}})
{
"_id" : ObjectId("4b2d75476cc613d5ee930164"),
Type-Specific Queries | 61
VB.NET PDF Convert to HTML SDK: Convert PDF to html files in vb.
Embed converted html files in html page or iframe. Export PDF form data to html form in .NET WinForms and ASP.NET. Turn PDF images to HTML images in VB.NET.
best pdf merger; pdf merge
C# HTML5 PDF Viewer SDK to view PDF document online in C#.NET
PDF; Merge PDF Files; Split PDF Document; Remove Password from PDF; Change PDF Permission Settings. FREE TRIAL: HOW TO: XDoc.HTML5 Viewer for C#▶: C# ASP.NET:
c# merge pdf pages; append pdf
"title" : "A blog post",
"content" : "...",
"comments" : [
{
"name" : "bob",
"email" : "bob@example.com",
"content" : "good post."
}
]
}
Both "title" and "content" are still returned, even though they weren’t explicitly
included in the key specifier.
Returning a matching array element
"$slice" is helpful when you know the index of the element, but sometimes you want
whichever array element matched your criteria. You can return the matching element
with the $-operator. Given the blog example above, you could get Bob’s comment back
with:
> db.blog.posts.find({"comments.name" : "bob"}, {"comments.$" : 1})
{
"_id" : ObjectId("4b2d75476cc613d5ee930164"),
"comments" : [
{
"name" : "bob",
"email" : "bob@example.com",
"content" : "good post."
}
]
}
Note that this only returns the first match for each document: if Bob had left multiple
comments on this post, only the first one in the "comments" array would be returned.
Array and range query interactions
Scalars (non-array elements) in documents must match each clause of a query’s criteria.
For example, if you queried for {"x" : {"$gt" : 10, "$lt" : 20}}, "x" would have
to be both greater than 10 and less than 20. However, if a document’s "x" field is an array,
the document matches if there is an element of "x" that matches each part of the criteria
but each query clause can match a different array element.
The best way to understand this behavior is to see an example. Suppose we have the
following documents:
{"x" : 5}
{"x" : 15}
{"x" : 25}
{"x" : [5, 25]}
62 | Chapter 4: Querying
VB.NET PDF File Split Library: Split, seperate PDF into multiple
Split PDF file into two or multiple files in ASP.NET webpage online. Support to break a large PDF file into smaller files in .NET WinForms.
pdf mail merge; all jpg to one pdf converter
C# HTML5 Viewer: Load, View, Convert, Annotate and Edit PDF
HTML5 Viewer for C# .NET. Related Resources. To view, convert, edit, process, protect, sign PDF files, please refer to XDoc.PDF SDK for .NET overview.
c# pdf merge; add pdf files together
If we wanted to find all documents where "x" is between 10 and 20, one might naively
structure a query as db.test.find({"x" : {"$gt" : 10, "$lt" : 20}}) and expect
to get back one document: {"x" : 15}. However, running this, we get two:
> db.test.find({"x" : {"$gt" : 10"$lt" : 20}})
{"x" : 15}
{"x" : [5, 25]}
Neither 5 nor 25 is between 10 and 20, but the document is returned because 25 matches
the first clause (it is greater than 25) and 5 matches the second clause (it is less than 20).
This makes range queries against arrays essentially useless: a range will match any multi-
element array. There are a couple of ways to get the expected behavior.
First, you can use "$elemMatch" to force MongoDB to compare both clauses with a single
array element. However, the catch is that "$elemMatch" won’t match non-array elements:
> db.test.find({"x" : {"$elemMatch" : {"$gt" : 10"$lt" : 20}})
> // no results
The document {"x" : 15} no longer matches the query, because the "x" field is not an
array.
If you have an index over the field that you’re querying on (see Chapter 5), you can use
min() and max() to limit the index range traversed by the query to your "$gt" and "$lt"
values:
> db.test.find({"x" : {"$gt" : 10"$lt" : 20}).min({"x" : 10}).max({"x" : 20})
{"x" : 15}
Now this will only traverse the index from 10 to 20, missing the 5 and 25 entries. You
can only use min() and max() when you have an index on the field you are querying
for, though, and you must pass all fields of the index to min() and max().
Using min() and max() when querying for ranges over documents that may include
arrays is generally a good idea: if you look at the index bounds for a "$gt“/”$lt" query
over an array, you can see that it’s horribly inefficient. It basically accepts any value, so
it will search every index entry, not just those in the range.
Querying on Embedded Documents
There are two ways of querying for an embedded document: querying for the whole
document or querying for its individual key/value pairs.
Querying for an entire embedded document works identically to a normal query. For
example, if we have a document that looks like this:
{
"name" : {
"first" : "Joe",
"last" : "Schmoe"
Type-Specific Queries | 63
VB.NET Create PDF from Word Library to convert docx, doc to PDF in
PDF; Merge PDF Files; Split PDF Document; Remove Password from PDF; Change PDF Permission Settings. FREE TRIAL: HOW TO: XDoc.HTML5 Viewer for C#▶: C# ASP.NET:
c# merge pdf; acrobat combine pdf files
C# PDF Convert to SVG SDK: Convert PDF to SVG files in C#.net, ASP
Instantly convert all PDF document pages to SVG image files in C#.NET class application. Perform high-fidelity PDF to SVG conversion in both ASP.NET web and
reader combine pdf; pdf merge files
},
"age" : 45
}
we can query for someone named Joe Schmoe with the following:
> db.people.find({"name" : {"first" : "Joe""last" : "Schmoe"}})
However, a query for a full subdocument must exactly match the subdocument. If Joe
decides to add a middle name field, suddenly this query won’t work anymore; it doesn’t
match the entire embedded document! This type of query is also order-sensitive:
{"last" : "Schmoe", "first" : "Joe"} would not be a match.
If possible, it’s usually a good idea to query for just a specific key or keys of an embedded
document. Then, if your schema changes, all of your queries won’t suddenly break
because they’re no longer exact matches. You can query for embedded keys using dot-
notation:
> db.people.find({"name.first" : "Joe""name.last" : "Schmoe"})
Now, if Joe adds more keys, this query will still match his first and last names.
This dot notation is the main difference between query documents and other document
types. Query documents can contain dots, which mean “reach into an embedded docu‐
ment.” Dot notation is also the reason that documents to be inserted cannot contain
the . character. Oftentimes people run into this limitation when trying to save URLs as
keys. One way to get around it is to always perform a global replace before inserting or
after retrieving, substituting a character that isn’t legal in URLs for the dot character.
Embedded document matches can get a little tricky as the document structure gets more
complicated. For example, suppose we are storing blog posts and we want to find com‐
ments by Joe that were scored at least a 5. We could model the post as follows:
> db.blog.find()
{
"content" : "...",
"comments" : [
{
"author" : "joe",
"score" : 3,
"comment" : "nice post"
},
{
"author" : "mary",
"score" : 6,
"comment" : "terrible post"
}
]
}
64 | Chapter 4: Querying
Now, we can’t query using db.blog.find({"comments" : {"author" : "joe",
"score" : {"$gte" : 5}}}). Embedded document matches have to match the whole
document, and this doesn’t match the "comment" key. It also wouldn’t work to do
db.blog.find({"comments.author" : "joe", "comments.score" : {"$gte" :
5}}), because the author criteria could match a different comment than the score cri‐
teria. That is, it would return the document shown above: it would match "author" :
"joe" in the first comment and "score" : 6 in the second comment.
To correctly group criteria without needing to specify every key, use "$elemMatch". This
vaguely-named conditional allows you to partially specify criteria to match a single
embedded document in an array. The correct query looks like this:
> db.blog.find({"comments" : {"$elemMatch" : {"author" : "joe"
"score" : {"$gte" : 5}}}})
"$elemMatch" allows us to “group” our criteria. As such, it’s only needed when you have
more than one key you want to match on in an embedded document.
$where Queries
Key/value pairs are a fairly expressive way to query, but there are some queries that they
cannot represent. For queries that cannot be done any other way, there are "$where"
clauses, which allow you to execute arbitrary JavaScript as part of your query. This allows
you to do (almost) anything within a query. For security, use of "$where" clauses should
be highly restricted or eliminated. End users should never be allowed to execute arbi‐
trary "$where" clauses.
The most common case for using "$where" is to compare the values for two keys in a
document. For instance, suppose we have documents that look like this:
> db.foo.insert({"apple" : 1"banana" : 6"peach" : 3})
> db.foo.insert({"apple" : 8"spinach" : 4"watermelon" : 4})
We’d like to return documents where any two of the fields are equal. For example, in
the second document, "spinach" and "watermelon" have the same value, so we’d like
that document returned. It’s unlikely MongoDB will ever have a $-conditional for this,
so we can use a "$where" clause to do it with JavaScript:
> db.foo.find({"$where" : function () {
... for (var current in this) {
...     for (var other in this) {
...         if (current != other && this[current== this[other]) {
...             return true;
...         }
...     }
... }
... return false;
... }});
$where Queries | 65
If the function returns true, the document will be part of the result set; if it returns
false, it won’t be.
"$where" queries should not be used unless strictly necessary: they are much slower
than regular queries. Each document has to be converted from BSON to a JavaScript
object and then run through the "$where" expression. Indexes cannot be used to satisfy
"$where", either. Hence, you should use "$where" only when there is no other way of
doing the query. You can cut down on the penalty by using other query filters in com‐
bination with "$where". If possible, an index will be used to filter based on the non-
$where clauses; the "$where" expression will be used only to fine-tune the results.
Another way of doing complex queries is to use one of the aggregation tools, which are
covered in Chapter 7.
Server-Side Scripting
You must be very careful with security when executing JavaScript on the server. If done
incorrectly, server-side JavaScript is susceptible to injection attacks similar to those that
occur in a relational database. However, by following certain rules around accepting
input, you can use JavaScript safely. Alternatively, you can turn off JavaScript execution
altogether by running mongod with the --noscripting option.
The security issues with JavaScript are all related to executing user-provided programs
on the server. You want to avoid doing that, so make sure you aren’t accepting user input
and passing it directly to mongod. For example, suppose you want to print “Hello,
name!”, where name is provided by the user. A naive approach might be to write a Java‐
Script function such as the following:
> func = "function() { print('Hello, "+name+"!'); }"
If name is a user-defined variable, it could be the string "'); db.dropDatabase();
print('", which would turn the code into this:
> func = "function() { print('Hello, '); db.dropDatabase(); print('!'); }"
Now, if you run this code, your entire database will be dropped!
To prevent this, you should use a scope to pass in the name. In Python, for example, this
looks like this:
func = pymongo.code.Code("function() { print('Hello, '+username+'!'); }",
{"username"name})
Now the database will harmlessly print this:
Hello'); db.dropDatabase(); print('!
Most drivers have a special type for sending code to the database, since code can actually
be a composite of a string and a scope. A scope is a document that maps variable names
to values. This mapping becomes a local scope for the JavaScript function being
66 | Chapter 4: Querying
executed. Thus, in the example above, the function would have access to a variable called
username, whose value would be the string that the user gave.
The shell does not have a code type that includes scope; you can only
use strings or JavaScript functions with it.
Cursors
The database returns results from find using a cursor. The client-side implementations
of cursors generally allow you to control a great deal about the eventual output of a
query. You can limit the number of results, skip over some number of results, sort results
by any combination of keys in any direction, and perform a number of other powerful
operations.
To create a cursor with the shell, put some documents into a collection, do a query on
them, and assign the results to a local variable (variables defined with "var" are local).
Here, we create a very simple collection and query it, storing the results in the cursor
variable:
> for(i=0i<100i++) {
...     db.collection.insert({x : i});
... }
> var cursor = db.collection.find();
The advantage of doing this is that you can look at one result at a time. If you store the
results in a global variable or no variable at all, the MongoDB shell will automatically
iterate through and display the first couple of documents. This is what we’ve been seeing
up until this point, and it is often the behavior you want for seeing what’s in a collection
but not for doing actual programming with the shell.
To iterate through the results, you can use the next method on the cursor. You can use
hasNext to check whether there is another result. A typical loop through results looks
like the following:
> while (cursor.hasNext()) {
...     obj = cursor.next();
...     // do stuff
... }
cursor.hasNext() checks that the next result exists, and cursor.next() fetches it.
The cursor class also implements JavaScript’s iterator interface, so you can use it in a
forEach loop:
> var cursor = db.people.find();
> cursor.forEach(function(x) {
...     print(x.name);
Cursors | 67
... });
adam
matt
zak
When you call find, the shell does not query the database immediately. It waits until
you start requesting results to send the query, which allows you to chain additional
options onto a query before it is performed. Almost every method on a cursor object
returns the cursor itself so that you can chain options in any order. For instance, all of
the following are equivalent:
> var cursor = db.foo.find().sort({"x" : 1}).limit(1).skip(10);
> var cursor = db.foo.find().limit(1).sort({"x" : 1}).skip(10);
> var cursor = db.foo.find().skip(10).limit(1).sort({"x" : 1});
At this point, the query has not been executed yet. All of these functions merely build
the query. Now, suppose we call the following:
> cursor.hasNext()
At this point, the query will be sent to the server. The shell fetches the first 100 results
or first 4 MB of results (whichever is smaller) at once so that the next calls to next or
hasNext will not have to make trips to the server. After the client has run through the
first set of results, the shell will again contact the database and ask for more results with
getMore request. getMore requests basically contain an identifier for the query and
ask the database if there are any more results, returning the next batch if there are. This
process continues until the cursor is exhausted and all results have been returned.
Limits, Skips, and Sorts
The most common query options are limiting the number of results returned, skipping
a number of results, and sorting. All these options must be added before a query is sent
to the database.
To set a limit, chain the limit function onto your call to find. For example, to only
return three results, use this:
> db.c.find().limit(3)
If there are fewer than three documents matching your query in the collection, only the
number of matching documents will be returned; limit sets an upper limit, not a lower
limit.
skip works similarly to limit:
> db.c.find().skip(3)
This will skip the first three matching documents and return the rest of the matches. If
there are fewer than three documents in your collection, it will not return any
documents.
68 | Chapter 4: Querying
Documents you may be interested
Documents you may be interested