When creating a simple MongoDB query, I have a question about the ordering of conditions in the query - for example (Mongoose.js syntax):
conditions = { archived: false, first_name: "Billy" };
vs.
conditions = { first_name: "Billy", archived: false };
..in a simple find() function:
User.find(conditions, function(err, users) { <some logic> });
..assuming a simple single-key indexing strategy:
UserSchema.index( { first_name: 1, archived: 1} );
..does the order of the conditions listed above matter?
IMPORTANT: I know the order DOES MATTER for compound indexes, but per above I am curious about single-key index queries. Also interested in cases of totally non-indexed queries since we're here. :)
ALTERNATE EXPLANATION: Put another way, assuming 100 User
s (50 archived and 50 not), given two possible internal MongoDB searching strategies:
archived
users, then search through the remaining 50 non-archived users with the first_name
value of "Billy"User
documents for the first_name
value "Billy", and then filter the found objects by removing any Billys that are archived. ..I would assume #1 to be faster (potentially MUCH faster in large queries with more than two conditions). But regardless of which is faster and why, surely one of them is.
CORE QUESTION: Outside the vast and powerful world of compound indexes, does MongoDB know how to perform its most performant/quick searches/filters automatically, regardless of which fields and which ordering? Or do we need to tell the system what is best programmatically (via the order of conditions presented, etc)?
Because MongoDB can read indexes in both ascending and descending order, the direction of a single-key index does not matter.
As the references are stored in a array, it makes sense to preserve the order. MongoDB only gurantee order of documents based on a sort operation. Therefore, even if some queries will return the order you need it won't be guaranteed for every query.
MongoDB provides different types of logical query operators and $or operator is one of them. This operator is used to perform logical OR operation on the array of two or more expressions and select or retrieve only those documents that match at least one of the given expression in the array.
Performance. Because the index contains all fields required by the query, MongoDB can both match the query conditions and return the results using only the index. Querying only the index can be much faster than querying documents outside of the index.
I'm a little confused by your question, simply because the index you provide ({ first_name: 1, archived: 1 }
) is a compound index. All of the following queries will make use of that compound index:
conditions = { archived: false, first_name: "Billy" };
conditions = { first_name: "Billy", archived: false };
conditions = { first_name: "Billy" };
Now, let's assume we have two separate indexes, { first_name: 1 }
and { archived: 1 }
. In this case, MongoDB will do query optimization to determine which index is the most efficient to use. You can read more about the query optimization performed by MongoDB here.
The MongoDB query optimizer will thus likely use the same index for both of the multicondition queries you provided:
conditions = { archived: false, first_name: "Billy" };
conditions = { first_name: "Billy", archived: false };
Alternatively, you can use hint
to force MongoDB to use an index of your choosing. In general, this is probably not a good idea. You can also manually check which index is the most efficient for a specific query as detailed here.
You can see which index a query is using by using the .explain()
functionality in the Mongo shell. (If no index is used, you'll see "cursor" : "BasicCursor"
in the resulting document. On the other hand, if the compound index is being used, you'll see something like "cursor" : "BtreeCursor first_name_1_archived_1"
. If one of the single-field indexes was used, you might see "cursor" : "BtreeCursor archived_1"
.
Additionally, the search strategy for MongoDB works like this:
The query optimizer runs all possible query plans in parallel and picks the "best" one, however all of the query plans follow the strategy above. (The BasicCursor is a degenerate case: it traverses all of the documents & applies the predicate to each one.)
tl;dr? The Matcher is smart enough to match equality predicates when they're presented in any order.
Does that make sense?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With