Reputation: 241
With Cosmos DB for MongoDB API (Version 3.4), the following find query in combination with the method cursor sort seems to behave incorrectly:
db.test.find({"field1": "value1"}).sort({"field2": 1})
The error occurs, if all of the following conditions are met:
The error also occurs, if all of the following conditions are met:
The error message:
The index path corresponding to the specified order-by item is excluded.
The malfunction occurs only when using the CosmosDB, with native MongoDB (mongoDB Atlas, v4.0) it behaves correctly.
Azure Cosmos DB for MongoDB API with MongoDB 3.4 wire protocol (preview feature) is used. The problem occurs with both a MongoDB C#/.NET driver and the mongo shell.
In addition, the problem only occurs with find(). An equivalent aggregation pipeline containing $match and $sort behaves correctly.
Execute command in mongo shell (or the equivalent code with mongoDB C#/.NET driver):
db.test.find({"field1": "value1"}).sort({"field2": 1})
All documents that match the query criteria. If there are none, no documents should be returned.
Error: error: { "_t" : "OKMongoResponse", "ok" : 0, "code" : 2, "errmsg" : "Message: {\"Errors\":[\"The index path corresponding to the specified order-by item is excluded.\"]}\r\nActivityId: c50cc751-0000-0000-0000-000000000000, Request URI: /apps/[...]/, RequestStats: \r\nRequestStartTime: 2019-07-11T08:58:48.9880813Z, RequestEndTime: 2019-07-11T08:58:49.0081101Z, Number of regions attempted: 1\r\nResponseTime: 2019-07-11T08:58:49.0081101Z, StoreResult: StorePhysicalAddress: rntbd://[...]/, LSN: 359549, GlobalCommittedLsn: 359548, PartitionKeyRangeId: 0, IsValid: True, StatusCode: 400, SubStatusCode: 0, RequestCharge: 1, ItemLSN: -1, SessionToken: -1#359549, UsingLocalLSN: True, TransportException: null, ResourceType: Document, OperationType: Query\r\n, SDK: Microsoft.Azure.Documents.Common/2.4.0.0", [...]
Adding an additional "dummy" field to the sort document prevents the error:
db.test.find({"field1": "value1"}).sort({"field2": 1, "dummyfield": 1}).count()
The workaround is not satisfactory. It could falsify the result.
Am I doing something wrong, or is Cosmos DB behaving flawed here?
Upvotes: 14
Views: 13071
Reputation: 51
It seems you're encountering an issue specific to Azure Cosmos DB's MongoDB API when dealing with dynamically structured documents. A potent solution to this is leveraging Wildcard Indexes.
Wildcard indexes help you to index fields that are not consistent across all documents, serving ideally for collections with varied fields.
To solve your problem, create a wildcard index that encompasses all fields:
db.test.createIndex( { "$**" : 1 } )
By doing so, all fields within your collection will be indexed, mitigating the sort() method issue you're facing. It's a broad solution and it's recommended to review your indexing strategy periodically for optimal performance according to your application's querying patterns.
Learn more about wildcard indexes in Azure Cosmos DB's MongoDB API from the official documentation.
Upvotes: 2
Reputation: 117
CosmosDB does not fully implement the MongoDB API. Sorting is one of the limitations of using CosmosDB for MongoDB. For you to sort a collection you must index the field you are sorting with.
Upvotes: 0
Reputation: 241
According to Microsoft support, an index needs to be created on the field being sorted. The default indexes can be dropped and custom indexes created. As for the issue of not modifying the index every time a new field is added, there is no other alternative other than performing a client side sort. Unfortunately, client side sorting would take lot of CPU memory on the client side and the sort on index would take work when you would get more fields to index.
Thus I did not find a really satisfying solution:
Upvotes: 10