問題
こちらはPythonで書かれたコードですが、こんな感じでCosmosDBのコレクション上のデータにソート(以下例では”id”でソート)をかけようとしたときに、エラーがでてしまいました。
ローカルのMongoDBではこんなことは起きていなかったので、CosmosDB特有の問題が怪しい・・・
コード
max_id = tweetdata.aggregate([{'$sort': {'id': -1 }}, {'$limit': 1}]).next()["id"]
エラー
OperationFailure: Error=2, Details='Response status code does not indicate success: BadRequest (400); Substatus: 0; ActivityId: 2b14951c-7fae-433a-ac08-7bb8ad4edce9; Reason: (Response status code does not indicate success: BadRequest (400); Substatus: 0; ActivityId: 2b14951c-7fae-433a-ac08-7bb8ad4edce9; Reason: (Response status code does not indicate success: BadRequest (400); Substatus: 0; ActivityId: 2b14951c-7fae-433a-ac08-7bb8ad4edce9; Reason: (Message: {"Errors":["The index path corresponding to the specified order-by item is excluded."]} ActivityId: 2b14951c-7fae-433a-ac08-7bb8ad4edce9, Request URI: xxx, RequestStats: Microsoft.Azure.Cosmos.Tracing.TraceData.ClientSideRequestStatisticsTraceDatum, SDK: Windows/10.0.19041 cosmos-netstandard-sdk/3.18.0);););, full error: {'ok': 0.0, 'errmsg': 'Error=2, Details=\'Response status code does not indicate success: BadRequest (400); Substatus: 0; ActivityId: 2b14951c-7fae-433a-ac08-7bb8ad4edce9; Reason: (Response status code does not indicate success: BadRequest (400); Substatus: 0; ActivityId: 2b14951c-7fae-433a-ac08-7bb8ad4edce9; Reason: (Response status code does not indicate success: BadRequest (400); Substatus: 0; ActivityId: 2b14951c-7fae-433a-ac08-7bb8ad4edce9; Reason: (Message: {"Errors":["The index path corresponding to the specified order-by item is excluded."]}\r\nActivityId: 2b14951c-7fae-433a-ac08-7bb8ad4edce9, Request URI: xxx, RequestStats: Microsoft.Azure.Cosmos.Tracing.TraceData.ClientSideRequestStatisticsTraceDatum, SDK: Windows/10.0.19041 cosmos-netstandard-sdk/3.18.0);););', 'code': 2, 'codeName': 'BadValue'}
原因と解決方法
ソート対象の列に対してインデックスが張られていないことが原因でした。
取り急ぎは、以下のようにIndexing Policyからソート対象列に対するインデックスを作成することで、エラーはでなくなりました。
なぜこんなことが起きたのか。
このあたりの議論がヒントになりました。
An index must match exactly the field being sorted on. The direction of the index is not relevant. Here your initial index was a composite index on three fields so could not be used for the sort.
https://docs.microsoft.com/en-us/answers/questions/258032/the-index-path-corresponding-to-the-specified-orde.html
Also adding the index on the field you are sorting on may resolve the issue. Its required to index the properties that we use in the sort query. If you are planning to sort on multiple fields, you need to create a compound index. Also go through these documents( Document1, Document2 ) for finding more information regarding the indexing.
According to Microsoft support, an index needs to be created on the field being sorted.
https://stackoverflow.com/questions/56988743/using-the-sort-cursor-method-without-the-default-indexing-policy-in-azure-cosm
ほう。公式ドキュメントも探してみる。複合インデックスの場合の記述ならあった。ここのことをいってるのかな・・?
MongoDB 用 API では、クエリで一度に複数のフィールドの並べ替えを実行できる必要がある場合、複合インデックスが必須となります。 並べ替える必要がない、複数のフィルターを使用するクエリの場合は、複合インデックスではなく、複数の単一フィールド インデックスを作成して、インデックス作成コストを節約します。
https://docs.microsoft.com/ja-jp/azure/cosmos-db/mongodb/mongodb-indexing#compound-indexes-mongodb-server-version-36
んでそもそもインデックスポリシーってなんだ?
公式Docはここにあった。
Azure Cosmos DB でのインデックス作成ポリシー
https://docs.microsoft.com/ja-jp/azure/cosmos-db/index-policy
MongoDB APIの場合は、規定で_id
フィールドとシャード キー (シャード コレクションのみ) のインデックスが自動的に作成されるらしい。
https://docs.microsoft.com/ja-jp/azure/cosmos-db/mongodb/mongodb-indexing
MongoDBにおけるインデックス作成のポイント
- インデックスは特殊なデータ構造で、データのクエリをおよそ 1 桁速くすることができます。
- 開発を開始するだけの場合は、すべてのフィールドに対するワイルドカード インデックスから始めることを強くお勧め ます。 これにより、開発が簡素化され、クエリの最適化が容易になります。
- 多くのフィールドを持つドキュメントでは、書き込みと更新の要求ユニット (RU) 料金が高くなる場合があります。 そのため、書き込みが多いワークロードがある場合は、ワイルドカード インデックスを使用するのではなく、個別のインデックスを作成する方法を選択する必要があります。
- 複合インデックスまたは複合インデックス内のフィールドごとに単一フィールド インデックスを使用すると、クエリでのフィルター処理で同じパフォーマンスが得られます。
勉強になりました。同じ問題で躓いた方の参考になりましたら幸いです。
おしまい
コメントを残す