Hi Richard,
I don't personally know why the limit exists but I can try to offer a workaround. You may also want to file a ticket with Google Cloud support to ask for a quota raise, although to be honest I have no idea if this is a quota we can actually raise or a hard limit. Can't hurt to ask!
Let's say you have the following query:
db.collection('widgets').where('category', '==', 'foo').where('location', '==', 'bar').orderBy('price', 'desc');
The simple way to index this would be a single compound index with three parts:
(category, asc), (location, asc), (price, desc)
That index matches the query perfectly and will give you the best performance. However you could also serve this query by creating two simpler indexes:
(category, asc), (price, desc)
(location, asc), (price, desc)
The query planner would be able to merge the two indexes and serve your three-clause query. Now I imagine your first question is "how does turning one index into two indexes help me?!?" which is valid! This helps when you have many overlapping equality queries, like this:
db.collection('widgets').where('category', '==', 'foo').where('name', '==', 'foo').where('location', '==', 'bar').where('quality', '==', 'baz').orderBy('price', 'desc');
db.collection('widgets').where('category', '==', 'foo').where('name', '==', 'foo').where('location', '==', 'bar').orderBy('price', 'desc');
db.collection('widgets').where('category', '==', 'foo').where('quality', '==', 'foo').where('location', '==', 'bar').orderBy('price', 'desc');
db.collection('widgets').where('name', '==', 'foo').where('quality', '==', 'foo').where('location', '==', 'bar').orderBy('price', 'desc');
db.collection('widgets').where('category', '==', 'foo').where('location', '==', 'bar').orderBy('price', 'desc');
db.collection('widgets').where('name', '==', 'foo').where('location', '==', 'bar').orderBy('price', 'desc');
db.collection('widgets').where('category', '==', 'foo').orderBy('price', 'desc');
db.collection('widgets').where('name', '==', 'foo').orderBy('price', 'desc');
db.collection('widgets').where('quality', '==', 'foo').orderBy('price', 'desc');
// .. etc
Rather than create a distinct index for each of these, you could serve all of them with this list of simple two-part indexes:
(category, asc), (price, desc)
(location, asc), (price, desc)
(name, asc), (price, desc)
(quality, asc), (price, desc)
Of course there's no such thing as a free lunch! By relying on the query planner to merge simple indexes you will give up some performance. All of this information (and much more) is available in the docs here:
I hope that's helpful!
Sam