We are in the process of writing tests for our Node/MongoDB backend and I have a question about finding documents.
My understanding is it's preferable to use Mongoose to get your documents as opposed to the MongoDB driver. In other words, doing Customer.findOne().exec() instead of setting up a db connection and then doing db.collection("customers").findOne().
Other than the first option (using Mongoose to find the doc) being slightly less verbose, I'm curious what the other reasons are. Is a straight MongoDB lookup a bigger drag on the database?
One of the great feature of mongoose is the built in validation mechanism. Also the Populate method to get data from multiple collections is an awesome characteristic of Mongoose.
In terms of query performance, here is a good read:
https://medium.com/#bugwheels94/performance-difference-in-mongoose-vs-mongodb-60be831c69ad
Hope this helps :)
Related
MongoDB is schemaless, which means a collection (table in relational DB) can contain documents (rows) of different structure - having different fields, for instance.
I'm new to Mongo, so I decided to use Mongoose which should make things a bit easier. Reading the guide:
Defining your schema
Everything in Mongoose starts with a Schema. Each schema maps to a
MongoDB collection and defines the shape of the documents within that
collection.
Notice at the last sentence. Doesn't it conflict with the schemaless philosophy of MongoDB? Or maybe it's that in 99% of cases, I want a collection of documents of the same structure, so in the introductory guide only that scenario is discussed? Does Mongoose even allow me to create schemaless collection?
MongoDB does not require a schema, but that confuses a lot of people from a standard SQL background so Mongoose is aimed at trying to bridge the gap between SQL and NoSQL. If you want to maintain a collection with different document types, than by all means do not use Mongoose.
If you're okay with the schemaless nature of MongoDB there is no reason to add additional abstractions and overhead to MongoDB which is what Mongoose surely applies.
The purpose of Mongoose is to use a Schema, there are other database drivers you can use to take advantage of MongoDBs Schemaless nature such as Mongoskin.
If you want to utilize the Mongoose's Schema Design and make an exeception you can use: Mongoose Strict.
According to the docs:
The strict option, (enabled by default), ensures that values passed to our model constructor that were not specified in our schema do not get saved to the db.
NoSQL doesn't mean no schema. It means, the database doesn't control schema. For instance, with MongoDB, you can look hard to find anything that determines a field in a document is a string, or a number or a date. The database doesn't care. You could store a number in a field in one document and in another document in the same collection, and in the same field, you could store a string. But, from a coding perspective, that can become quite hairy and would be bad practice. This is why you still have to define data types. So, you still need a schema of sorts and why Mongoose offers and, in fact, enforces this functionality.
Going a conceptual level higher now, the major concept of NoSQL is to put schema inside your code and not in some file of SQL commands i.e. not telling the DB what to expect in terms of data types and schema to be controlled by the database. So, instead of needing to have migration files/paths and versioning on database schema, you just have your code. ORMs, for example, try to bridge this issue too, where they often have automated migration systems.
ORMs also try to avoid the Object Relational Impedance Mismatch problem, which MongoDB avoids completely. Well, it doesn't have relationships per se, so the problem is avoided out of necessity.
Getting back to schema, with MongoDB and Mongoose, if you or one of your team make a change to the schema in the code, all your other team members need to do to get the database to work with it is pull in that new code. Voila, the schema is up-to-date and will work. No need to also pull in a copy of the newer migration file (to determine the new schema of the DB) to then have to run it on a (copy of the) db to update it too, just to continue programming. There is no need to make changes in schema in multiple places.
So, in the end, if you can imagine your schema is always in your code (only), making changes to an application with a database persisting state like MongoDB is a good bit simpler and even safer. (Safer, because code and schema can't get out of sync, as it's the one and the same.)
Mongoose (and MongoDB for that matter) seem to prefer the dbref/population idiom rather than traditional SQL relationships.
While I respect the simplicity of the solution proposed here: How to show related subdocument properties in Meteor
The MongoDB docs speak to DBRefs here:
http://docs.mongodb.org/manual/reference/database-references/#dbref-explanation
and Mongoose Populations are documented here: http://mongoosejs.com/docs/populate.html
While pulling an item from 1 query and passing it into another query is definitely one option the syntactic sugar of being able to pull a single query that provides all of the required data in one pull has it's advantages.
What is the Meteor philosophy on this?
The closest thing I know of to mongoose's populations is collection helpers. It works on both the client and the server and allows you to automatically transform documents into objects with useful methods.
As you'll see in the documentation, you can use these methods to, among other things, establish relationships between documents. For example if you have Books and Authors collections you can define a helper like this:
Books.helpers({
author: function() {
return Authors.findOne(this.authorId);
}
});
Which lets your write code this:
Books.findOne().author().firstName;
You still need to go through the effort of writing the join yourself, but once written you can use it everywhere.
I'm new to mongoDB and in a node project i'm using mongoose to create a schema for my database. I have come to understand that in my case i should be using embedded data instead of by reference. (http://docs.mongodb.org/manual/core/data-modeling-introduction/)
The structure that i need to store in the database is something like this:
book
| title
| | chapter
| | | content (url to a html file)
Coming from a mySQL world, i'm trying to understand the noSQL database concepts and i was wondering how one would design the mongoose schema.
Thx,
You can nest documents, and document arrays in a MongoDB document:
db.books.findOne();
can return a JSON:
{
isbn:"253GHST78F6",
title:"some book",
author:"Earnest Hemmingway",
chapters:[
{title:"chapter 1",content:"http://api.com/chapters/1.html"},
{title:"chapter 2",content:"http://api.com/chapters/2.html"}
]
}
But, there are a few more things to keep in mind when modeling a collection in MongoDB:
Model data as close as possible to what will be asked for: There are no Joins in MongoDB, so, try to keep all such data together (pre joined), that is supposed be queried together in future.
Nesting is good for queries but nested update and search is bad:
Indexing and searching inside nested documents, especially arrays, will be expensive.
Avoid placing any data in nested arrays, that is very frequently updated.
There are no Foriegn Keys in MongoDB. So, if you have multiple copies of same document nested under different collections, keeping all of them updated is your responsibility.
First take a look at this Martin Fowlers excellent video:
I think there is no better authority that can explain nosql, then Fowler. Especially knowing his sql background.
Second, MongoDB follows json schema. If you know how to work with json, you will know how to work with nosql (mongodb). Basic thing that needs to be understand is that Mongo schema is expressed in a language that is using it.
So, if you are using NodeJS with Mongo, you still have objects and array to work with. In simple words, Mongo is not forcing any particular schema. It is on developer to create his scheme based on his language/mongo driver.
So how would you express you data logic in your language ? If it is in form of JS object, then move that form to db.
I really like MongoDB, becuse it can be combined with some great JS tools like Underscore.js for all kind of data manipulations.
I am a super newbie to mongodb. I am using mongoose to access mongodb from node.js, and know how to get things to work, but I don't think I understand why it works the way it does.
Most importantly, I don't understand why mongoose has 'schema' when one of the standout features of mongodb is that it doesn't have schema. Could someone enlighten me? thank you.
Data without a schema is useless. You get a document from MongoDB, what do you do with it? Read some fields? You need to know the names, types and meanings of those fields. That’s a schema.
When people say that MongoDB “has no schema”, they really mean that it does not enforce schema the way SQL databases do. MongoDB pushes schema concerns up to your application level, where you can handle them more flexibly. For example, in order to add a new field to your documents, you don’t need to do an all-or-nothing ALTER on your collection—potentially millions of entries. You just add that field to your ODM (Mongoose) schema and you’re done.
The MongoDB sorting functions are pretty neato. Can you use them on objects and/or arrays that have nothing to do with the database itself?
var mongo = require('mongodb'),
Server = mongo.Server,
Db = mongo.Db,
sortingFun = mongo.internalSortFilterFunction(); // By the miracle of imagination, this is a made-up line.
There is, for example, this awesome little node project called sift: MongoDB inspired array filtering. But there are more similar tools, different opinions, and projects merging and disappearing.
Considering it's popularity, MongoDB is quite probably gonna hang around. For that reason, plus the added bonus of being exactly similar instead of pretty similar, I was wondering if a specific object/model/function within node-mongodb could be linked from the require('mongodb') specifically for using the sorting and filtering functions on custom objects/arrays.
The sorting is done in the mongo server, not the client. It's also not particularily fast -- big collections should be pre-sorted, but that's another issue.
The mongo server is afaik written in C++ and uses custom types, separate from the JS engine, called BSON.
So if there is no sort implementation on the client for javascript, which would be an absurd feature, you can't use server sort.
Edit: If you really really want to use the sort, performance be damned, you could insert js objects into the DB, effectively converting them to BSON in mongo collections. Then sort it and pull it from the DB. Indexes etc will need to be recreated for every call to that function. Mongodb also refuses to sort for big collections sans index (limit being somewhere around 1000 I believe)
PS. I haven't read the source. I can't imagine a JS realtime, indexless sort that matches the speed of MongoDB's sort esp. when distributed (sharded). But you can write node.js modules in C++, and if BSON is similar enough to V8 JS objects (wouldn't think so), you might be able to port it. I wouldn't go down that road because it's probably not going to be a big speed increase compared to reimplementing it in JS, a reimplementation which would be a lot easier to create and maintain.