Whenever this user does something, all the users we need to notify are right there. The
downside is that now you need to query the whole users collection to find everyone a
user follows (the opposite limitation as above).
Either of these options comes with an additional downside: they make your user docu‐
ment larger and more volatile. The "following" (or "followers") field often won’t
even need to be returned: how often do you want to list every follower? If users are
frequently followed or unfollowed, this can result in a lot of fragmentation, as well. Thus,
the final option neutralizes these downsides by normalizing even further and storing
subscriptions in another collection. Normalizing this far is often overkill, but it can be
useful for an extremely volatile field that often isn’t returned with the rest of the docu‐
ment. "followers" may be a sensible field to normalize this way.
Keep a collection that matches publishers to subscribers, with documents that look
something like this:
"_id" : ObjectId("51250a7ed86041c7dca81936"), // followee's "_id"
"followers" : [
This keeps your user documents svelte but takes an extra query to get the followers. As
"followers" arrays will generally change size a lot, this allows you to enable the usePo
werOf2Sizes on this collection while keeping the users collection as small as possible.
If you put this followers collection in another database, you can also compact it without
affecting the users collection too much.
Dealing with the Wil Wheaton effect
Regardless of which strategy you use, embedding only works with a limited number of
subdocuments or references. If you have celebrity users, they may overflow any docu‐
ment that you’re storing followers in. The typical way of compensating this is to have a
“continuation” document, if necessary. For example, you might have:
> db.users.find({"username" : "wil"})
"_id" : ObjectId("51252871d86041c7dca8191a"),
"username" : "wil",
"email" : "wil@example.com",
"tbc" : [
"followers" : [
Normalization versus Denormalization | 159
Pdf combine pages - Merge, append PDF files in C#.net, ASP.NET, MVC, Ajax, WinForms, WPF
Provide C# Demo Codes for Merging and Appending PDF Document
adding pdf pages together; batch pdf merger online
Pdf combine pages - 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
pdf mail merge; add two pdf files together
"_id" : ObjectId("512528ced86041c7dca8191e"),
"followers" : [
"_id" : ObjectId("5126510dd86041c7dca81924"),
"followers" : [
Then add application logic to support fetching the documents in the “to be continued”
("tbc") array.
Optimizations for Data Manipulation
To optimize your application, you must first know what its bottleneck is by evaluating
its read and write performance. Optimizing reads generally involves having the correct
indexes and returning as much of the information as possible in a single document.
Optimizing writes usually involves minimizing the number of indexes you have and
making updates as efficient as possible.
There is often a trade-off between schemas that are optimized for writing quickly and
those that are optimized for reading quickly, so you may have to decide which is a more
important for your application. Factor in not only the importance of reads versus writes,
but also their proportions: if writes are more important but you’re doing a thousand
reads to every write, you may still want to optimize reads first.
Optimizing for Document Growth
If you’re going to need to update data, determine whether or not your documents are
going to grow and by how much. If it is by a predictable amount, manually padding
your documents will prevent moves, making writes faster. Check your padding factor:
if it is about 1.2 or greater, consider using manual padding.
160 | Chapter 8: Application Design
C# PDF: C#.NET PDF Document Merging & Splitting Control SDK
List<BaseDocument> docList, String destFilePath) { PDFDocument.Combine(docList, destFilePath); }. For example, if the target PDF file has 8 pages and you
add pdf together; pdf split and merge
C# PDF File Split Library: Split, seperate PDF into multiple files
which C# developers can split target PDF document file by specifying a page or pages. If needed, developers can also combine generated split PDF document files
acrobat split pdf into multiple files; acrobat reader merge pdf files
When you manually pad a document, you create the document with a large field that
will later be removed. This preallocates the space that the document will eventually need.
For example, suppose you had a collection of restaurant reviews and your documents
looked like this:
"_id" : ObjectId(),
"restaurant" : "Le Cirque",
"review" : "Hamburgers were overpriced."
"userId" : ObjectId(),
"tags" : []
The "tags" field will grow as users add tags, so the application will often have to perform
an update like this:
> db.reviews.update({"_id" : id}, 
... {"$push" : {"tags" : {"$each" : ["French""fine dining""hamburgers"]}}}})
If "tags" generally doesn’t grow to more than 100 bytes, you could manually pad the
document to prevent any unwanted moves. If you leave the document without padding,
moves will definitely occur as "tags" grows. To pad, add a final field to the document
with whatever field name you’d like:
"_id" : ObjectId(),
"restaurant" : "Le Cirque",
"review" : "Hamburgers were overpriced."
"userId" : ObjectId(),
"tags" : [],
"garbage" : "........................................................"+
You can either do this on insert or, if the document is created with an upsert, use
"$setOnInsert" to create the field when the document is first inserted.
When you update the document, always "$unset" the "garbage" field:
> db.reviews.update({"_id" : id}, 
... {"$push" : {"tags" : {"$each" : ["French""fine dining""hamburgers"]}}},
...  "$unset" : {"garbage" : true}})
The "$unset" will remove the "garbage" field if it exists and be a no-op if it does not.
If your document has one field that grows, try to keep is as the last field in the document
(but before "garbage"). It is slightly more efficient for MongoDB not to have to rewrite
fields after "tags" if it grows.
Optimizations for Data Manipulation | 161
C# Word - Merge Word Documents in C#.NET
Combine and Merge Multiple Word Files into One Using C#. This part illustrates how to combine three Word files into a new file in C# application.
combine pdf files; pdf combine two pages into one
C# PowerPoint - Merge PowerPoint Documents in C#.NET
Combine and Merge Multiple PowerPoint Files into One Using C#. This part illustrates how to combine three PowerPoint files into a new file in C# application.
combine pdf; break pdf file into multiple files
Removing Old Data
Some data is only important for a brief time: after a few weeks or months it is just wasting
storage space. There are three popular options for removing old data: capped collections,
TTL collections, and dropping collections per time period.
The easiest option is to use a capped collection: set it to a large size and let old data “fall
off” the end. However, capped collections pose certain limitations on the operations
you can do and are vulnerable to spikes in traffic, temporarily lowering the length of
time that they can hold. See “Capped Collections” on page 109 for more information.
The second option is TTL collections: this gives you a finer-grain control over when
documents are removed. However, it may not be fast enough for very high-write-volume
collections: it removes documents by traversing the TTL index the same way a user-
requested remove would. If TTL collections can keep up, though, they are probably the
easiest solution. See “Time-To-Live Indexes” on page 114 for more information about
TTL indexes.
The final option is to use multiple collections: for example, one collection per month.
Every time the month changes, your application starts using this month’s (empty) col‐
lection and searching for data in both the current and previous months’ collections.
Once a collection is older than, say, six months, you can drop it. This can keep up with
nearly any volume of traffic, but it is more complex to build an application around, since
it has to use dynamic collection (or database) names and possibly query multiple
Planning Out Databases and Collections
Once you have sketched out what your documents look like, you must decide what
collections or databases to put them in. This is often a fairly intuitive process, but there
are some guidelines to keep in mind.
In general, documents with a similar schema should be kept in the same collection.
MongoDB generally disallows combining data from multiple collections, so if there are
documents that need to be queried or aggregated together, those are good candidates
for putting in one big collection. For example, you might have documents that are fairly
different “shapes,” but if you’re going to be aggregating them, they all need to live in the
same collection.
For databases, the big issues to consider are locking (you get a read/write lock per da‐
tabase) and storage. Each database resides in its own files and often its own directory
on disk, which means that you could mount different databases to different volumes.
Thus, you may want all items within a database to be of similar “quality,” similar access
pattern, or similar traffic levels.
162 | Chapter 8: Application Design
VB.NET PDF Page Insert Library: insert pages into PDF file in vb.
to add and insert one or multiple pages to existing simple ways to create VB application to combine .NET Imaging Processing and PDF document libraries.
attach pdf to mail merge in word; build pdf from multiple files
VB.NET PDF: Use VB.NET Code to Merge and Split PDF Documents
VB.NET program and it includes all pages information in APIs for Merging PDF Documents in VB.NET. Private Sub Combine(source As List(Of BaseDocument), destn As
acrobat merge pdf; c# merge pdf files into one
For example, suppose we have an application with several components: a logging com‐
ponent that creates a huge amount of not-very-valuable data, a user collection, and a
couple of collections for user-generated data. The user collections are high-value: it is
important that user data is safe. There is also a high-traffic collection for social activities,
which is of lower importance but not quite as unimportant as the logs. This collection
is mainly used for user notifications, so it is almost an append-only collection.
Splitting these up by importance, we might end up with three databases: logsactivi
ties, and users. The nice thing about this strategy is that you may find that your highest-
value data is also your smallest (for instance, users probably don’t generate as much data
as your logging does). You might not be able to afford an SSD for your entire data set,
but you might be able to get one for your users. Or use RAID10 for users and RAID0
for logs and activities.
Be aware that there are some limitations when using multiple databases: MongoDB
generally does not allow you to move data directly from one database to another. For
example, you cannot store the results of a MapReduce in a different database than you
ran the MapReduce on and you cannot move a collection from one database to another
with the renameCollection command (e.g., you can rename foo.bar as foo.baz, but not
Managing Consistency
You must figure out how consistent your application’s reads need to be. MongoDB sup‐
ports a huge variety in consistency levels, from always reading your own writes to read‐
ing data of unknown oldness. If you’re reporting on the last year of activity, you might
only need data that’s correct to the last couple of days. Conversely, if you’re doing real-
time trading, you might need to immediately read the latest writes.
To understand how to achieve these varying levels of consistency, it is important to
understand what MongoDB is doing under the hood. The server keeps a queue of re‐
quests for each connection. When the client sends a request, it will be placed at the end
of its connection’s queue. Any subsequent requests on the connection will occur after
the enqueued operation is processed. Thus, a single connection has a consistent view
of the database and can always read its own writes.
Note that this is a per-connection queue: if we open two shells, we will have two con‐
nections to the database. If we perform an insert in one shell, a subsequent query in the
other shell might not return the inserted document. However, within a single shell, if
we query for the document after inserting, the document will be returned. This behavior
can be difficult to duplicate by hand, but on a busy server interleaved inserts and queries
are likely to occur. Often developers run into this when they insert data in one thread
and then check that it was successfully inserted in another. For a moment or two, it looks
like the data was not inserted, and then it suddenly appears.
Managing Consistency | 163
Online Merge PDF files. Best free online merge PDF tool.
the editor area you can rearrange them or delete single pages. Also you can add more PDFs to combine them and merge as easy as possible to merge your PDF files
attach pdf to mail merge; batch merge pdf
VB.NET PowerPoint: Merge and Split PowerPoint Document(s) with PPT
Just like we need to combine PPT files, sometimes, we also the split PPT document will contain slides/pages 1-4 If you want to see more PDF processing functions
add pdf pages together; merge pdf files
This behavior is especially worth keeping in mind when using the Ruby, Python, and
Java drivers, because all three use connection pooling. For efficiency, these drivers open
multiple connections (a pool) to the server and distribute requests across them. They
all, however, have mechanisms to guarantee that a series of requests is processed by a
single connection. There is detailed documentation on connection pooling in various
languages on the MongoDB wiki.
When you send reads to a replica set secondary (see Chapter 11), this becomes an even
larger issue. Secondaries may lag behind the primary, leading to reading data from
seconds, minutes, or even hours ago. There are several ways of dealing with this, the
easiest being to simply send all reads to the primary if you care about staleness. You
could also set up an automatic script to detect lag on a secondary and put it into main‐
tenance mode if it lags too far behind. If you have a small set, it might be worth using
"w" : setSize as a write concern and sending subsequent reads to the primary if
getLastError does not return successfully.
Migrating Schemas
As your application grows and your needs change, your schema may have to grow and
change as well. There are a couple of ways of accomplishing this, and regardless of the
method you chose, you should carefully document each schema that your application
has used.
The simplest method is to simply have your schema evolve as your application requires,
making sure that your application supports all old versions of the schema (e.g., accepting
the existence or non-existence of fields or dealing with multiple possible field types
gracefully). This technique can become messy, particularly if you have conflicting ver‐
sions. For instance, one version might require a "mobile" field and one version might
require not having a "mobile" field but does require another field, and yet another
version thinks that the "mobile" field is optional. Keeping track of these requirements
can gradually turn code into spaghetti.
To handle changing requirements in a slightly more structured way you can include a
"version" field (or just "v") in each document and use that to determine what your
application will accept for document structure. This enforces your schema more rig‐
orously: a document has to be valid for some version of the schema, if not the current
one. However, it still requires supporting old versions.
The final option is to migrate all of your data when the schema changes. Generally this
is not a good idea: MongoDB allows you to have a dynamic schema in order to avoid
migrates because they put a lot of pressure on your system. However, if you do decide
to change every document, you will need to ensure that all documents were successfully
updated. MongoDB does not support atomic multiupdates (either they all happen or
164 | Chapter 8: Application Design
they all don’t across multiple documents). If MongoDB crashes in the middle of a mi‐
grate, you could end up with some updated and some non-updated documents.
When Not to Use MongoDB
While MongoDB is a general-purpose database that works well for most applications,
it isn’t good at everything. Here are some tasks that MongoDB is not designed to do:
• MongoDB does not support transactions, so systems that require transactions
should use another data store. There are a couple of ways to hack in simple
transaction-like semantics, particularly on a single document, but there is no da‐
tabase enforcement. Thus, you can make all of your clients agree to obey whatever
semantics you come up with (e.g., “Check the "locks" field before doing any op‐
eration”) but there is nothing stopping an ignorant or malicious client from messing
things up.
• Joining many different types of data across many different dimensions is something
relational databases are fantastic at. MongoDB isn’t supposed to do this well and
most likely never will.
• Finally, one of the big (if hopefully temporary) reasons to use a relational database
over MongoDB is if you’re using tools that don’t support MongoDB. From SQLAl‐
chemy to Wordpress, there are thousands of tools that just weren’t built to support
MongoDB. The pool of tools that support MongoDB is growing but is hardly the
size of relational databases’ ecosystem, yet.
When Not to Use MongoDB | 165
Documents you may be interested
Documents you may be interested