Hi Brent!
Sorry for taking so long to get back to you.
The answer to your question is: the database is not going to be any more efficient than doing the queries client side -- IF you have designed your schema properly.
1) Let's begin by looking at how you'd do this in SQL:
CREATE TABLE dept (deptno NUMBER CONSTRAINT pk_dept PRIMARY KEY,
dname VARCHAR2(30) );
CREATE TABLE emp (
empid NUMBER CONSTRAINT pk_emp PRIMARY KEY,
ename VARCHAR(20),
deptno NUMER CONSTRAINT fk_deptno FOREIGN KEY REFERENCES dept(deptno) );
First off: this creates two indexes "behind your back": one on dept.deptno, one on emp.empid.
Second: consider how you would query these tables:
SELECT empid, ename FROM emp, dept
WHERE
dept.dname = 'SALES'
JOIN
dept.deptno = emp.deptno
ORDER BY ename;
Note that unless you index 'emp.deptno', this query is going to be slow (since it will otherwise perform a full table scan on 'emp'). Unless you index 'dept.dname', it will have to perform a full table scan on 'dept'.
You're now at no less than FOUR indexes.
This query is going to force the RDBMS to do the following:
A) Read the 'dept.dname' index to find the location of the row(s) where "dname = 'SALES'"
B) Fetch the matching row(s) from the 'dept' table, and save off the set of 'deptno' values
C) Read the 'emp.deptno' index to find the locations of the matching rows in the 'emp' table
D) Fetch the matching rows from the 'emp' table
E) Sort the result set in-memory
2) Now, let's consider how to do this in MongoDB. For legibility, I'm going to use integers for the _id field, but everything I will do will work with ObjectIDs as well:
> db.dept.save( {_id: 1, name: 'Sales'} );
> db.dept.save( {_id: 2, name: 'Marketing'} );
> db.dept.save( {_id: 3, name: 'Support'} );
> db.emp.save( { _id: 1, name: 'Ben', dept: 1 } );
> db.emp.save( { _id: 2, name: 'William', dept: 3 } );
> db.emp.save( { _id: 3, name: 'Jenna', dept: 3 } );
> db.emp.save( { _id: 4, name: 'Steven', dept: 3 } );
To make this efficient, I'll create a secondary index on the 'dept' field in the 'emp' collection, and the 'name' field in the 'dept' collection:
> db.emp.ensureIndex( dept: 1 );
> db.dept.ensureIndex( name: 1 );
By default, there are already indexes on "dept._id" and "emp._id".
To find all of the employees in the "Support" department, I need to do two queries:
> result = db.dept.findOne({name: 'Support'}, {_id:1} );
{ "_id" : 3 }
> desired_dept = result["_id"];
3
> db.emp.find( { dept: desired_dept }).sort({name:1}).pretty();
{ "_id" : 3, "name" : "Jenna", "dept" : 3 }
{ "_id" : 4, "name" : "Steven", "dept" : 3 }
{ "_id" : 2, "name" : "William", "dept" : 3 }
In terms of the actual work done, there are the same number of indexes involved, and the same number of operations involved as with the SQL example. The only difference is that I had to build one portion of the query in the client side instead of on the server side.
Let me know if you have further questions.
-William