The logic of my query goes like this:
- Filter documents based on arbitrarily many and non-predetermined fields. The filter conditions can total to hundreds. But the worst case is that there are no filter conditions at all, hence 100% of documents will pass.
- Lookup / join all of the documents returned in
1.
from another collection / table to further filter the above documents. For example, looking up blocked users to remove them. This lookup / join will be indexed. - Compute derived numeric fields for all documents that pass.
- Sort the passing documents based on arbitrarily many fields, which may include the derived fields from
3.
- Limit and then return only 50 of these documents to the client. The sorting and limit must happen last because of
2.
and3.
Let's suppose that the collection / table has 10 million documents. In worst case scenario, all 10 million documents must be examined in order to return just 50 to the client. There is no way to avoid this.
- What are the solutions to optimize this query for the worst case?
- In particular, is sharding a viable solution? For example, if there are 100 shards, then each server will only have to examine 100,000 documents in worst case. If there are 1000 shards, then each server will have to examine 10,000 documents in worst case. This query will be a scatter and gather, which will be held back by the slowest server. However, the slowest server will only have to examine 10,000 documents maximum.
Schema of main user collection / table:
{
_id: "ObjectId",
age: "number",
city: "string",
school: "string",
height: "number",
// etc., potentially hundreds of other attributes describing the user
}
Schema of the lookup / join collection:
{
blocker: "objectId from main user collection",
blocked: "objectId from main user collection"
}
Schema of output documents:
{
age: "number",
city: "string",
school: "string",
height: "number",
derived_field: "number",
// etc. potentially others depending on filter
}
Cost feasible? If my APP can get to 10 million users, then the 1000 servers should not be an issue?