MongoDB


when you can have circular links of hte same type (users apear everywhere) its more a graph database than document. http://www.sarahmei.com/blog/2013/11/11/why-you-should-never-use-mongodb/
db.adminCommand('listDatabases');


$ ./mongo
> use mongo-db
> show collections
>  db.meetups.insert({name:"MEAN SF Developers"})
> show collections
> db.meetups.find()
db.meetups.insert({name:"MEAN SF Developers", speaker: "Mike Moser")
> db.meetups.find()


var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/test');

var Cat = mongoose.model('Cat', { name: String });

var kitty = new Cat({ name: 'Zildjian' });
kitty.save(function (err) {
  if (err) // ...
  console.log('meow');
});

type "help" for help

type "tutorial" to start the tutorial

Basic Mongo Console CRUD Operations

Create
db.scores.save({a: 99}); //This says, "save the document '{a: 99}' to the 'scores' collection."
     db.scores.find();
for(i=0; i<10; i++) { db.scores.save({a: i, exam: 5}) }; // Since the shell only displays 10 results at time, you'll need to enter the 'it' command to iterate over the rest.finding all documents where a == 2:

Query (Read)
db.scores.find({a: 2});
documents where a > 15? db.scores.find({a: {'$gt': 15}});
Operators
$lt - '<', $lte - '<=', $gte - '>=', $ne - '!=', $in - 'is in array', $nin - '! in array'
db.scores.find({a: {'$in': [2, 3, 4]}});
db.scores.find({a: {'$gte': 2, '$lte': 4}});
Updates
Now create a couple documents like these for updating, and Make sure they were saved by called db.users.find():
db.users.save({name: 'Johnny', languages: ['ruby', 'c']});
db.users.save({name: 'Sue', languages: ['scala', 'lisp']});
Update the first document like so:
db.users.update({name: 'Johnny'}, {name: 'Cash', languages: ['english']});

Update Operators
The previous update replaced the entire document, but MongoDB also supports partial updates to documents. For example, you can set a value:
db.users.update({name: 'Cash'}, {'$set': {'age': 50} });
You can also push and pull items from arrays:
db.users.update({name: 'Sue'}, {'$pull': {'languages': 'scala'} });
db.users.update({name: 'Sue'}, {'$push': {'languages': 'ruby'} });
Delete
db.users.remove({name: 'Sue'}); //delete matching documents only
db.scores.remove(); //To delete everything from a collection:

CRUD

MongoDB documents are BSON documents.
BSON is a binary representation of JSON with additional type information. In the documents, the value of a field can be any of the BSON data types, including other documents, arrays, and arrays of documents.

MongoDB stores documents in collections.
A collection is a group of related documents that have a set of shared common indexes. Collections are analogous to a table in relational databases.

find
db.users.find({age:{'gt' : 18}}).sort({age:1})                                                     // Specify in the sort parameter the field or fields to sort by and a value of 1 or -1 to specify an ascending or descending sort respectively.
db.users.find( { age: { $gt: 18 } }, { name: 1, address: 1 } ).limit(5)                  
// age is the query criteria, name and address are projection, you can include or exclude a field (via 0 or 1) Except for excluding the _id field in inclusive projections, you cannot mix exclusive and inclusive projections. To suppress the _id field from the result set, specify _id: 0 in the projection document.
db.students.find()
                   .skip(pageNumber > 0 ? ((pageNumber-1)*nPerPage) : 0) // skip(n): skips the first n records. e.g. for paged result
                   .limit(nPerPage)
                   .forEach( function(student) { print(student.name + "<p>"); } );

Consider using range-based pagination for these kinds of tasks. That is, query for a range of objects, using logic within the application to determine the pagination rather than the database itself. This approach features better index utilization, if you do not need to easily jump to a specific page.

AND / OR
db.inventory.find( { type: 'food', price: { $lt: 9.95 } } )
db.inventory.find( { $or: [ { qty: { $gt: 100 } }, { price: { $lt: 9.95 } } ] } )

For fields that contain arrays, MongoDB provides the following projection operators: $elemMatch,$slice, and $.
For related projection functionality in the aggregation framework pipeline, use the $projectpipeline stage.

Cursor
By default, the server will automatically close the cursor after 10 minutes of inactivity or if client has exhausted the cursor. To override this behavior, you can specify the noTimeout wire protocol flag in your query; however, you should either close the cursor manually or exhaust the cursor. In the mongo shell, you can set the noTimeout flag:
var myCursor = db.inventory.find().addOption(DBQuery.Option.noTimeout);


Cursor Isolation
Because the cursor is not isolated during its lifetime, intervening write operations on a document may result in a cursor that returns a document more than once if that document has changed. To handle this situation, see the information on snapshot mode.

The db.serverStatus() method returns a document that includes a metrics field.

Index
var typeValue = <someUserInput>;
db.inventory.find( { type: typeValue } );

To improve the performance of this query, add an ascending, or a descending, index to theinventory collection on the type field. [1] In the mongo shell, you can create indexes using the db.collection.ensureIndex() method:
db.inventory.ensureIndex( { type: 1 } )

Write
In MongoDB, write operations target a single collection. All write operations in MongoDB are atomic on the level of a single document. No insert, update, or remove can affect more than one document atomically.

db.users.update( { age: { $gt: 18 } }, { $set: { status: "A" } }, { multi: true } )
This update operation on the users collection sets the status field to A for the documents that match the criteria of age greater than 18.
with upsert flag if can not find the document will create one.

The db.collection.save() method can either update an existing document or insert a document if the document cannot be found by the _id field.

Write Concern
Write concern describes the guarantee that MongoDB provides when reporting on the success of a write operation. a weak write concern, write operations return quickly.


Read Isolation
MongoDB allows clients to read documents inserted or modified before it commits these modifications to disk, regardless of write concern level or journaling configuration. As a result, applications may observe two classes of behaviors:
For systems with multiple concurrent readers and writers, MongoDB will allow clients to read the results of a write operation before the write operation returns.
If the mongod terminates before the journal commits, even if a write returns successfully, queries may have read data that will not exist after the mongod restarts.

Atomicity / Transaction
The modification of a single document is always atomic, even if the write operation modifies multiple embedded documents within that document. No other operations are atomic.

If a write operation modifies multiple documents, the operation as a whole is not atomic, and other operations may interleave. You can, however, attempt to isolate a write operation that affects multiple documents using the isolation operator.

db.users.insert({name:"john", age:26, groups:["news", "sport"]})

queries select documents from a single collection.

To manually compare the performance of a query using more than one index, you can use the hint()method in conjunction with the explain() method.

Data Models

The key decision in designing data models for MongoDB applications revolves around the structure of documents and how the application represents relationships between data. There are two tools that allow applications to represent these relationships: references and embedded documents.
references
normalized. Applications can resolve these references to access the related data

In general, use normalized data models:
when embedding would result in duplication of data but would not provide sufficient read performance advantages to outweigh the implications of the duplication.
to represent more complex many-to-many relationships.
to model large hierarchical data sets.

References provides more flexibility than embedding. However, client-side applications must issue follow-up queries to resolve the references. In other words, normalized data models can require more round trips to the server.

See Model One-to-Many Relationships with Document References for an example of referencing. For examples of various tree models using references, see Model Tree Structures.

embedded
denormalized, Embedded documents capture relationships between data by storing related data in a single document structure. MongoDB documents make it possible to embed document structures as sub-documents in a field or array within a document. These denormalized data models allow applications to retrieve and manipulate related data in a single database operation.

In general, embedding provides better performance for read operations, as well as the ability to request and retrieve related data in a single database operation. Embedded data models make it possible to update related data in a single atomic write operation. However, embedding related data in documents may lead to situations where documents grow after creation. Document growth can impact write performance and lead to data fragmentation. Furthermore, documents in MongoDB must be smaller than the maximum BSONdocument size.

To interact with embedded documents, use dot notation to “reach into” embedded documents. See query for data in arrays and query data in sub-documents for more examples on accessing data in arrays and embedded documents.

Operational Factors and Data Models
Document Growth
Atomicity
Sharding
Indexes
Split large Number of Collections e.g. to seperate log types for efficient batch processing
Time to live (TTL)

GridFS
GridFS is a specification for storing and retrieving files that exceed the BSON-document size limit of 16MB.




Model One-to-One Relationships with Embedded Documents
{ _id: "joe", name: "Joe Bookreader" }     --->     { patron_id: "joe", street: "123 Fake Street", city: "Faketon", state: "MA", zip: "12345" }

Model One-to-Many Relationships with Embedded Documents
one-to-many relationship between patron and address data, the patron has multiple address entities.

{ _id: "joe", name: "Joe Bookreader" }
{ patron_id: "joe", street: "123 Fake Street", city: "Faketon", state: "MA", zip: "12345" }
{ patron_id: "joe", street: "1 Some Other Street", city: "Boston", state: "MA", zip: "12345" }
TO:
{ _id: "joe", name: "Joe Bookreader", addresses: [ { street: "123 Fake Street", city: "Faketon", state: "MA", zip: "12345" }, { street: "1 Some Other Street", city: "Boston", state: "MA", zip: "12345" } ] }

Model One-to-Many Relationships with Document References
publisher and book relationships, advantage of referencing over embedding to avoid repetition of the publisher information

{ title: "MongoDB: The Definitive Guide", author: [ "Kristina Chodorow", "Mike Dirolf" ], published_date: ISODate("2010-09-24"), pages: 216, language: "English", publisher: { name: "O'Reilly Media", founded: 1980, location: "CA" } }
{ title: "50 Tips and Tricks for MongoDB Developer", author: "Kristina Chodorow", published_date: ISODate("2011-05-06"), pages: 68, language: "English", publisher: { name: "O'Reilly Media", founded: 1980, location: "CA" } }

keep the publisher information in a separate collection from the book collection and store books as its arrays. if the number of books per publisher is unbounded, this data model would lead to mutable, growing arrays

{ name: "O'Reilly Media", founded: 1980, location: "CA", books: [12346789, 234567890, ............................................] }
{ _id: 123456789, title: "MongoDB: The Definitive Guide", author: [ "Kristina Chodorow", "Mike Dirolf" ], published_date: ISODate("2010-09-24"), pages: 216, language: "English" }
{ _id: 234567890, title: "50 Tips and Tricks for MongoDB Developer", author: "Kristina Chodorow", published_date: ISODate("2011-05-06"), pages: 68, language: "English" }

To avoid mutable, growing arrays, store the publisher reference inside the book document:
{ _id: "oreilly", name: "O'Reilly Media", founded: 1980, location: "CA" }
{ _id: 123456789, title: "MongoDB: The Definitive Guide", author: [ "Kristina Chodorow", "Mike Dirolf" ], published_date: ISODate("2010-09-24"), pages: 216, language: "English", publisher_id: "oreilly" }
{ _id: 234567890, title: "50 Tips and Tricks for MongoDB Developer", author: "Kristina Chodorow", published_date: ISODate("2011-05-06"), pages: 68, language: "English", publisher_id: "oreilly" }

Modeling Trees
Model Tree Structures with Parent References
db.categories.insert( { _id: "MongoDB", parent: "Databases" } )
db.categories.insert( { _id: "dbm", parent: "Databases" } )
db.categories.insert( { _id: "Databases", parent: "Programming" } )
db.categories.insert( { _id: "Languages", parent: "Programming" } )
db.categories.insert( { _id: "Programming", parent: "Books" } )
db.categories.insert( { _id: "Books", parent: null } )

The query to retrieve the parent of a node is fast and straightforward:
db.categories.findOne( { _id: "MongoDB" } ).parent

You can create an index on the field parent to enable fast search by the parent node:
db.categories.ensureIndex( { parent: 1 } )

You can query by the parent field to find its immediate children nodes:
db.categories.find( { parent: "Databases" } )

The Parent Links pattern provides a simple solution to tree storage but requires multiple queries to retrieve subtrees.

Model Tree Structures with Child References
in addition to the tree node, document stores in an array the id(s) of the node’s children.
db.categories.insert( { _id: "MongoDB", children: [] } )
db.categories.insert( { _id: "dbm", children: [] } )
db.categories.insert( { _id: "Databases", children: [ "MongoDB", "dbm" ] } )
db.categories.insert( { _id: "Languages", children: [] } )
db.categories.insert( { _id: "Programming", children: [ "Databases", "Languages" ] } )
db.categories.insert( { _id: "Books", children: [ "Programming" ] } )

The query to retrieve the immediate children of a node is fast and straightforward:
db.categories.findOne( { _id: "Databases" } ).children

You can create an index on the field children to enable fast search by the child nodes:
db.categories.ensureIndex( { children: 1 } )

You can query for a node in the children field to find its parent node as well as its siblings:
db.categories.find( { children: "MongoDB" } )

The Child References pattern provides a suitable solution to tree storage as long as no operations on subtrees are necessary. This pattern may also provide a suitable solution for storing graphs where a node may have multiple parents.


Model Tree Structures with an Array of Ancestors
in addition to the tree node, document stores in an array the id(s) of the node’s ancestors or path.

db.categories.insert( { _id: "MongoDB", ancestors: [ "Books", "Programming", "Databases" ], parent: "Databases" } )
db.categories.insert( { _id: "dbm", ancestors: [ "Books", "Programming", "Databases" ], parent: "Databases" } )
db.categories.insert( { _id: "Databases", ancestors: [ "Books", "Programming" ], parent: "Programming" } )
db.categories.insert( { _id: "Languages", ancestors: [ "Books", "Programming" ], parent: "Programming" } )
db.categories.insert( { _id: "Programming", ancestors: [ "Books" ], parent: "Books" } )
db.categories.insert( { _id: "Books", ancestors: [ ], parent: null } )

The query to retrieve the ancestors or path of a node is fast and straightforward:
db.categories.findOne( { _id: "MongoDB" } ).ancestors

You can create an index on the field ancestors to enable fast search by the ancestors nodes:
db.categories.ensureIndex( { ancestors: 1 } )

You can query by the field ancestors to find all its descendants:
db.categories.find( { ancestors: "Programming" } )

The Array of Ancestors pattern provides a fast and efficient solution to find the descendants and the ancestors of a node by creating an index on the elements of the ancestors field. This makes Array of Ancestors a good choice for working with subtrees. The Array of Ancestors pattern is slightly slower than the Materialized Paths pattern but is more straightforward to use.


Model Tree Structures with Materialized Paths

in addition to the tree node, document stores as a string the id(s) of the node’s ancestors or path. Although the Materialized Paths pattern requires additional steps of working with strings and regular expressions, the pattern also provides more flexibility in working with the path, such as finding nodes by partial paths.

db.categories.insert( { _id: "Books", path: null } )
db.categories.insert( { _id: "Programming", path: ",Books," } )
db.categories.insert( { _id: "Databases", path: ",Books,Programming," } )
db.categories.insert( { _id: "Languages", path: ",Books,Programming," } )
db.categories.insert( { _id: "MongoDB", path: ",Books,Programming,Databases," } )
db.categories.insert( { _id: "dbm", path: ",Books,Programming,Databases," } )

You can query to retrieve the whole tree, sorting by the field path:
db.categories.find().sort( { path: 1 } )

You can use regular expressions on the path field to find the descendants of Programming:
db.categories.find( { path: /,Programming,/ } )

You can also retrieve the descendants of Books where the Books is also at the topmost level of the hierarchy:
db.categories.find( { path: /^,Books,/ } )

To create an index on the field path use the following invocation:
db.categories.ensureIndex( { path: 1 } )

This index may improve performance depending on the query:
For queries of the Books sub-tree (e.g. /^,Books,/) an index on the path field improves the query performance significantly.
For queries of the Programming sub-tree (e.g. /,Programming,/), or similar queries of sub-tress, where the node might be in the middle of the indexed string, the query must inspect the entire index.
For these queries an index may provide some performance improvement if the index is significantly smaller than the entire collection.


Model Tree Structures with Nested Sets

The Nested Sets pattern identifies each node in the tree as stops in a round-trip traversal of the tree. The application visits each node in the tree twice; first during the initial trip, and second during the return trip. The Nested Sets pattern stores each tree node in a document; in addition to the tree node, document stores the id of node’s parent, the node’s initial stop in the left field, and its return stop in the right field.

db.categories.insert( { _id: "Books", parent: 0, left: 1, right: 12 } )
db.categories.insert( { _id: "Programming", parent: "Books", left: 2, right: 11 } )
db.categories.insert( { _id: "Languages", parent: "Programming", left: 3, right: 4 } )
db.categories.insert( { _id: "Databases", parent: "Programming", left: 5, right: 10 } )
db.categories.insert( { _id: "MongoDB", parent: "Databases", left: 6, right: 7 } )
db.categories.insert( { _id: "dbm", parent: "Databases", left: 8, right: 9 } )

You can query to retrieve the descendants of a node:
var databaseCategory = db.categories.findOne( { _id: "Databases" } );
db.categories.find( { left: { $gt: databaseCategory.left }, right: { $lt: databaseCategory.right } } );

The Nested Sets pattern provides a fast and efficient solution for finding subtrees but is inefficient for modifying the tree structure. As such, this pattern is best for static trees that do not change.





















Comments