mongo-views
Supports MongoDB 2.2 <= 3.0
This is a MongoDB skunkworks project to enable queryable views within the shell. Views are like virtual collections, that can be queried as regular collections.
They support:
- Criteria
- Projections
- Joins
- Nesting
Why might you want this? Well lets say you want to save a query for regular reuse. Say you have an employees
collection:
dbemployees
and we want all managers from an employee
collection. Then you could create a view via:
dbemployees
and query/sort/limit it as though it was a collection via
db_managers/* yields =>{ "_id": ObjectId("54f9e58e1d8a2ac246213516"), "name": "Paul", "manager": true, "dob": ISODate("1983-08-10T04:00:00Z"), "uid": 3}{ "_id": ObjectId("54f9e58e1d8a2ac246213518"), "name": "Aimee", "manager": true, "dob": ISODate("1945-03-20T04:00:00Z"), "uid": 50}*/
it's virtual, so if you add to the underlying collection(s)
dbemployees
then the same view query yields:
db_managers;/* yields =>{ "_id": ObjectId("54f9e58e1d8a2ac246213516"), "name": "Paul", "manager": true, "dob": ISODate("1983-08-10T04:00:00Z"), "uid": 3}{ "_id": ObjectId("54f9e5b41d8a2ac24621351a"), "name": "Ian", "manager": true, "dob": ISODate("1995-02-20T05:00:00Z"), "uid": 99}{ "_id": ObjectId("54f9e58e1d8a2ac246213518"), "name": "Aimee", "manager": true, "dob": ISODate("1945-03-20T04:00:00Z"), "uid": 50}*/
you can of course add criteria to the find()
db_managers;/* yields =>{ "_id": ObjectId("54f9e58e1d8a2ac246213516"), "name": "Paul", "manager": true, "dob": ISODate("1983-08-10T04:00:00Z"), "uid": 3}*/
you can then create nested views just as easily
db_managers db_senior_managers/* yields =>{ "_id": ObjectId("54f9d8b3f088c1c44badce68"), "name": "Paul", "manager": true, "dob": ISODate("1983-08-10T04:00:00Z")}{ "_id": ObjectId("54f9d8b3f088c1c44badce6a"), "name": "Aimee", "manager": true, "dob": ISODate("1945-03-20T04:00:00Z")}*/
We can see all our views so far via
show views/* yields =>managerssenior_managers*/
Maybe we don't want senior managers to show the _id
field, then we use a projection
// remove view firstdb_senior_managers; db_managers db_senior_managers/* yields =>{ "name": "Paul", "manager": true, "dob": ISODate("1983-08-10T04:00:00Z"), "uid": 3}{ "name": "Aimee", "manager": true, "dob": ISODate("1945-03-20T04:00:00Z"), "uid": 50}*/
we can even combine projections as in
db_senior_managers/* yields =>{ "name": "Paul", "dob": ISODate("1983-08-10T04:00:00Z")}{ "name": "Aimee", "dob": ISODate("1945-03-20T04:00:00Z")}*/
it's just a cursor, so we can sort and limit as expected:
db_senior_managers/* yields =>{ "name": "Aimee", "manager": true, "dob": ISODate("1945-03-20T04:00:00Z")}*/
Now what about joins ? Easy. Join to the users
.
// add usersdbusers dbemployees db_employees_with_email /* yields =>{ "_id": { "from": ObjectId("54f9ebb1257b0c8dc73be97a"), "to": ObjectId("54f9f1c4067bf2a2b99c53b1") }, "name": "Aimee", "manager": true, "dob": ISODate("1945-03-20T04:00:00Z"), "uid": 50, "id": 50, "email": "aimee@example.com"}{ "_id": { "from": ObjectId("54f9ec10461b20c42cabc3d4"), "to": ObjectId("54f9f1c4067bf2a2b99c53b0") }, "name": "Ian", "manager": true, "dob": ISODate("1995-02-20T05:00:00Z"), "uid": 99, "id": 99, "email": "ian@example.com"}{ "_id": { "from": ObjectId("54f9ebb1257b0c8dc73be979"), "to": ObjectId("54f9f1c4067bf2a2b99c53b2") }, "name": "Mary", "dob": ISODate("1985-06-12T04:00:00Z"), "uid": 20, "id": 20, "email": "mary@example.com"}{ "_id": { "from": ObjectId("54f9ebb1257b0c8dc73be978"), "to": ObjectId("54f9f1c4067bf2a2b99c53b3") }, "name": "Paul", "manager": true, "dob": ISODate("1983-08-10T04:00:00Z"), "uid": 3, "id": 3, "email": "paul@example.com"}*/
It's all a cursor, so guess what? You can even join a view to another view!
Want to see what's inside your view? Inspect it!
db_employees_with_email/* yields =>{ "name": "employees_with_email", "target": "employees", "query": { }, "projection": { }, "join": { "target": "users", "from": "uid", "to": "id" }}*/
Moreover, these views persist. Both when you switch DBs via use [db]
or by restarting the shell.
Views are virtual, and only save the state of the query used to create them. This means that each time a query is performed on a view, the latest collection data is fetched.
Installation
-
In POSIX environments, run
make
-
In WinX environments, please add
mongorc.js
to your MongoDB installation folder (if it doesn't exist), runnpm run build
to generate the browserify bundle, and finally copy the contents ofdist/bundle.js
into ``mongorc.js`.
Basic Usage
Create
dbcollection|view
See all views in DB
show views
Inspect a view
db_view
Query
db_view:DBQuery
Drop
db_view
Criteria
- Under the hood, views composed criteria using
$and
operators. So allcriteria
parameters in the view, along with any find criteria in thefind
call, will be condensed into a singlecriteria
object.
ie. in the above example,
dbemployees;db_managers;
Will yield
dbemployees;
Projection
-
MongoDB allows for projections in the
find
function. Fields can be enabled or disabled, either as whitelists or blacklists see MongoDB docs. -
In order to properly combine projections, we must combine the two sets in certain ways:
- For matched fields in both the view and the find projection, we bitwise AND them (meaning that unless they are both true, the field is off)
- For fields enabled in the base projection, only those enabled in the find projection will remain.
- For fields disabled in the base projection, all of those disabled in the find projection will be added.
Egs.
Case 1:
dbemployees;db_managers; // yields =>dbemployees; // id set to 0 from 1~0
Case 2:
dbemployees;db_managers; // yields =>dbemployees; // id removed as not in find() projection
Case 3:
dbemployees;db_managers; // yields =>dbemployees; // id removed as not in find() projection
Join
Currently supports a single join to another collection or view.
Naming conflicts are solved by prefixing the fields with collection or view name and an underscore.
_id
field is a compound key of from
and to
_ids
API:
join: target: collection|view from: String // foreign key in this collection or view to: String // unique key in target collection or view
Guidelines
-
Views are scoped to the DB level
-
View names must be unique, and cannot match any given collection name in that DB
-
Views based on dropped collections or views will be removed automatically
-
Joins are performed in-memory, and may take a long time for large collections
Run Tests
First time grab deps: npm install
Then run npm test