

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# 機能の違い: Amazon DocumentDB と MongoDB
<a name="functional-differences"></a>

Amazon DocumentDB (MongoDB 互換性) と MongoDB の機能上の違いを以下に示します。

**Topics**
+ [Amazon DocumentDB の機能上の利点](#functional-differences.functional-benefits)
+ [機能的な違いの更新](#functional-differences.updated-functional-differences)
+ [MongoDB との機能的な違い](#functional-differences.with-mongodb)

## Amazon DocumentDB の機能上の利点
<a name="functional-differences.functional-benefits"></a>

### 暗示的なトランザクション
<a name="functional-differences.implicit-transactions"></a>

Amazon DocumentDB では、すべての CRUD ステートメント (`findAndModify`、`update`、`insert`、`delete`) は、複数のドキュメントを変更するオペレーションにおいてもアトミック性および整合性を保証します。Amazon DocumentDB 4.0 の起動により、マルチステートメントおよびマルチコレクションオペレーションの ACID プロパティを提供する明示的なトランザクションがサポートされるようになりました。Amazon DocumentDB でのトランザクションの使用の詳細については、「[Amazon DocumentDB でのトランザクション](transactions.md)」を参照してください。

アトミック性および整合性の両方の動作を満たす複数のドキュメントを変更する Amazon DocumentDB のオペレーションの例を次に示します。

```
db.miles.update(
    { "credit_card": { $eq: true } },
    { $mul: { "flight_miles.$[]": NumberInt(2) } },
    { multi: true }
)
```

```
db.miles.updateMany(
    { "credit_card": { $eq: true } }, 
    { $mul: { "flight_miles.$[]": NumberInt(2) } }
)
```

```
db.runCommand({
  update: "miles",
  updates: [
    {
      q: { "credit_card": { $eq: true } },
      u: { $mul: { "flight_miles.$[]": NumberInt(2) } },
      multi: true
    }
  ]
})
```

```
db.products.deleteMany({
  "cost": { $gt: 30.00 }
})
```

```
db.runCommand({
  delete: "products",
  deletes: [{ q: { "cost": { $gt: 30.00 } }, limit: 0 }]
})
```

`updateMany` や `deleteMany` などの一括オペレーションを構成する個々のオペレーションはアトミックですが、一括オペレーション全体はアトミックではありません。たとえば、個々の挿入オペレーションがエラーなしで正常に実行された場合、`insertMany` オペレーション全体はアトミックです。`insertMany` オペレーションでエラーが発生した場合、`insertMany` オペレーション内の各挿入ステートメントはアトミックオペレーションとして実行されます。`insertMany`、`updateMany`、および `deleteMany` オペレーションに ACID プロパティが必要な場合の場合は、トランザクションを使用することをお勧めします。

## 機能的な違いの更新
<a name="functional-differences.updated-functional-differences"></a>

Amazon DocumentDB は、お客様より依頼のあった機能からさかのぼって、MongoDB との互換性を改善し続けています。このセクションでは、移行とアプリケーション構築を容易にするため、Amazon DocumentDB から削除された機能的な違いについて説明します。

**Topics**
+ [配列インデックス作成](#functional-differences.array-indexing)
+ [マルチキーインデックス](#functional-differences.multi-key-indexes)
+ [文字列内の null 文字](#functional-differences.strings)
+ [ロールベースアクセスコントロール](#functional-differences.role_based_access_control)
+ [`$regex` インデックス作成](#functional-differences.regex-indexing)
+ [ネストされたドキュメントの投影](#functional-differences.nested-docs)

### 配列インデックス作成
<a name="functional-differences.array-indexing"></a>

2020 年 4 月 23 日以降、Amazon DocumentDB で 2,048 バイトを超える配列のインデックスを作成する機能がサポートされるようになりました。配列内の個々のキーの制限は依然として 2,048 バイトのままであり、これは MongoDB と一貫しています。

新しいインデックスを作成する場合、強化された機能を利用するためのアクションは必要ありません。既存のインデックスがある場合、インデックスを削除してから再作成することで、強化された機能を利用できます。強化された機能を使用した現在のインデックスバージョンは `"v" : 3` です。

**注記**  
本番クラスターの場合、インデックスの削除はアプリケーションのパフォーマンスに影響を与える可能性があります。本番システムに変更を加える場合、最初にテストし、注意して進めることをお勧めします。さらに、インデックスの再作成にかかる時間は、コレクションの全体的なデータサイズの関数になります。

次のコマンドを使用して、インデックスのバージョンをクエリできます。

```
db.collection.getIndexes()
```

このオペレーションによる出力は、次のようになります。この出力では、インデックスのバージョンは `"v" : 3` です。これは最新のインデックスバージョンです。

```
[
    {
        "v" : 3,
        "key" : {
        "_id" : 1
        },
        "name" : "_id_",
        "ns" : "test.test"
    }
]
```

### マルチキーインデックス
<a name="functional-differences.multi-key-indexes"></a>

2020 年 4 月 23 日より、Amazon DocumentDB では同じ配列内に複数のキーを持つ複合インデックスを作成する機能がサポートされるようになりました。

新しいインデックスを作成する場合、強化された機能を利用するためのアクションは必要ありません。既存のインデックスがある場合、インデックスを削除してから再作成することで、強化された機能を利用できます。強化された機能を使用した現在のインデックスバージョンは `"v" : 3` です。

**注記**  
本番クラスターの場合、インデックスの削除はアプリケーションのパフォーマンスに影響を与える可能性があります。本番システムに変更を加える場合、最初にテストし、注意して進めることをお勧めします。さらに、インデックスの再作成にかかる時間は、コレクションの全体的なデータサイズの関数になります。

次のコマンドを使用して、インデックスのバージョンをクエリできます。

```
db.collection.getIndexes()
```

このオペレーションによる出力は、次のようになります。この出力では、インデックスのバージョンは `"v" : 3` です。これは最新のインデックスバージョンです。

```
[
    {
        "v" : 3,
        "key" : {
            "_id" : 1
        },
        "name" : "_id_",
        "ns" : "test.test"
    }
]
```

### 文字列内の null 文字
<a name="functional-differences.strings"></a>

2020 年 6 月 22 日現在、Amazon DocumentDB が文字列で null 文字 (`'\0'`) をサポートするようになりました。

### ロールベースアクセスコントロール
<a name="functional-differences.role_based_access_control"></a>

2020 年 3 月 26 日現在、Amazon DocumentDB は組み込みロールによるロールベースのアクセスコントロール (RBAC) をサポートしています。詳細については [ロールベースのアクセスコントロール](role_based_access_control.md) を参照してください。

### `$regex` インデックス作成
<a name="functional-differences.regex-indexing"></a>

2020 年 6 月 22 日現在、Amazon DocumentDB は `$regex` 演算子がインデックスを活用する機能をサポートするようになりました。

`$regex` 演算子を使用してインデックスを活用するには、`hint()` コマンドを使用する必要があります。`hint()` を使用する際は、`$regex` を適用するフィールドの名前を指定する必要があります。たとえば、`product` というフィールドにインデックス名 `p_1` というインデックスがある場合、`db.foo.find({product: /^x.*/}).hint({product:1})` では `p_1` インデックスを使用しますが、`db.foo.find({product: /^x.*/}).hint(“p_1”)` ではインデックスを使用しません。インデックスが選択されているかどうかを確認するには、`explain()` コマンドを使用するか、低速クエリのログ記録にプロファイラーを使用します。例えば、`db.foo.find({product: /^x.*/}).hint(“p_1”).explain()`。

**注記**  
`hint()` メソッドは、一度に 1 つのインデックスでのみ使用できます。

`$regex` クエリでのインデックスの使用は、プレフィックスを利用し、`i`、`m`、または `o` 正規表現オプションを指定しない正規表現クエリに最適化されます。

`$regex` でインデックスを使用する場合は、重複値の数がコレクション内のドキュメントの総数の 1% 未満であるごく一部のフィールドにインデックスを作成することをお勧めします。例えば、コレクションに 100,000 個のドキュメントが含まれている場合、同じ値が発生する回数が 1000 回以下のフィールドにのみインデックスを作成します。

### ネストされたドキュメントの投影
<a name="functional-differences.nested-docs"></a>

Amazon DocumentDB と MongoDB 3.6 における `$project` 演算子と機能の差は、Amazon DocumentDB 4.0 で解決されていますが、Amazon DocumentDB 3.6 では未サポートのままです。

Amazon DocumentDB 3.6 は、投影を適用するときにネストされたドキュメントの最初のフィールドのみを考慮しますが、MongoDB 3.6 はサブドキュメントを解析し、各サブドキュメントにも投影を適用します。

例えば、投影が `“a.b.c”: 1` とすると、この動作は Amazon DocumentDB と MongoDB の両方で期待どおりに機能します。ただし、投影が `{a:{b:{c:1}}}` だとすると、Amazon DocumentDB 3.6 は投影を `a` にのみ適用し、`b` や `c` には適用しません。Amazon DocumentDB 4.0では、投影 `{a:{b:{c:1}}}` は `a`、`b`、および`c` に適用されます。

## MongoDB との機能的な違い
<a name="functional-differences.with-mongodb"></a>

**Topics**
+ [`$vectorSearch` operator](#functional-differences.vector-search)
+ [`OpCountersCommand`](#functional-differences.op-counter)
+ [管理データベースとコレクション](#functional-differences.admin-databases)
+ [`cursormaxTimeMS`](#functional-differences.cursormaxTimeMS)
+ [explain()](#functional-differences.explain)
+ [インデックスビルド](#functional-differences.background-indexes)
+ [パスに空のキーでルックアップ](#functional-differences.lookup-empty)
+ [MongoDB API、オペレーション、およびデータ型](#functional-differences.mongo-apis)
+ [`mongodump` および `mongorestore` ユーティリティ](#functional-differences.mongodump-mongorestore)
+ [結果の順序](#functional-differences.result-ordering)
+ [再試行可能な書き込み](#functional-differences.retryable-writes)
+ [スパースインデックス](#functional-differences.sparse-index)
+ [`$all` 式内での `$elemMatch` の使用](#functional-differences.elemMatch)
+ [フィールド名のドル (\$1) とドット (.)](#functional-differences-dollardot)
+ [`$lookup`](#functional-differences.lookup)
+ [`$natural` および逆順のソート](#functional-differences.natural)

### `$vectorSearch` operator
<a name="functional-differences.vector-search"></a>

Amazon DocumentDB は、独立した演算子として `$vectorSearch` をサポートしていません。代わりに、`$search` 演算子内の `vectorSearch` をサポートします。詳細については、「[Amazon DocumentDB のベクトル検索](vector-search.md)」を参照してください。

### `OpCountersCommand`
<a name="functional-differences.op-counter"></a>

Amazon DocumentDB の `OpCountersCommand` 動作は MongoDB の `opcounters.command` 動作と次のように異なります。
+ MongoDB は挿入、更新、`opcounters.command` 削除を除くすべてのコマンドをカウントしますが、Amazon DocumentDB は`OpCountersCommand` コマンドも除外します。`find`
+ Amazon DocumentDB は、一部の内部コマンドを `OpCountersCommand` に加算します。

### 管理データベースとコレクション
<a name="functional-differences.admin-databases"></a>

Amazon DocumentDB は管理者データベースまたはローカルデータベースをサポートしていません。また、MongoDB `system.*` または `startup_log` コレクションもサポートしていません。

### `cursormaxTimeMS`
<a name="functional-differences.cursormaxTimeMS"></a>

Amazon DocumentDB では、`cursor.maxTimeMS` はカウンターを `getMore` リクエストごとにリセットします。したがって、3000 ミリ秒 `maxTimeMS` が指定されている場合、クエリは 2800 ミリ秒 になり、`getMore` リクエストは 300 ミリ秒 かかり、カーソルはタイムアウトしません。カーソルがタイムアウトするのは、単一のオペレーション（クエリまたは個々の `getMore` リクエスト）の場合のみです。指定された `maxTimeMS` よりも多くかかります。さらに、カーソルの実行時間をチェックするスイーパーは、5 分単位で実行されます。

### explain()
<a name="functional-differences.explain"></a>

Amazon DocumentDB は、分散型で耐障害性のある自己修復ストレージシステムを利用する専用データベースエンジンで MongoDB 3.6、4.0、5.0、8.0 APIs をエミュレートします。その結果、クエリプランと `explain()` の出力は、Amazon DocumentDB と MongoDB の間で異なる場合があります。クエリプランを制御する場合は、`$hint` 演算子を使用して優先インデックスの選択を強制できます。

### インデックスビルド
<a name="functional-differences.background-indexes"></a>

Amazon DocumentDB では、任意の時点でコレクションにおいてインデックスの作成が 1 つのみ許可されます。フォアグラウンドまたはバックグラウンドのいずれかで実行されます。インデックス構築が現在進行中のときに、`createIndex()` または `dropIndex()` などの操作が同じコレクションで発生した場合、新しく試行された操作は失敗します。

デフォルトでは、Amazon DocumentDB と MongoDB バージョン 4.0 のインデックスビルドはフォアグラウンドで行われます。MongoDB バージョン 4.2 以降では、createIndexes またはそのシェルヘルパー、`createIndex()` および `createIndexes()` に指定されている場合、バックグラウンドインデックス構築オプションは無視されます。

有効期限 (TTL) インデックスは、インデックスの構築が完了した後、ドキュメントの期限切れが開始されます。

### パスに空のキーでルックアップ
<a name="functional-differences.lookup-empty"></a>

パスの一部として (例 : `x.`、`x..b`) 空の文字列を含むキーを調べると、オブジェクトには空の文字列キーパス (例 : `{"x" : [ { "" : 10 }, { "b" : 20 } ]}`) が配列内にあり、Amazon DocumentDB は MongoDB で同じルックアップを実行する場合とは異なる結果を返します。

MongoDB では、空の文字列キーがパスルックアップの末尾にない場合に、配列内の空のキーパスルックアップが期待どおりに機能します。ただし、空の文字列キーがパスルックアップの末尾にある場合、配列は検索されません。

ただし、Amazon DocumentDB では、配列内の最初の要素のみが読み取られます。`getArrayIndexFromKeyString` は空の文字列を`0` に変換するため、文字列キールックアップは配列インデックスルックアップとして扱われるためです。

### MongoDB API、オペレーション、およびデータ型
<a name="functional-differences.mongo-apis"></a>

Amazon DocumentDB は、MongoDB 3.6、4.0、5.0、および 8.0 APIs。サポートされている機能の最新リストについては、「[Amazon DocumentDB でサポートされている MongoDB API、オペレーション、およびデータ型](mongo-apis.md)」を参照してください。

### `mongodump` および `mongorestore` ユーティリティ
<a name="functional-differences.mongodump-mongorestore"></a>

Amazon DocumentDB は管理者データベースをサポートしないため、`mongodump` または `mongorestore` ユーティリティを使用するときに、管理者データベースをダンプまたは復元しません。`mongorestore` を使用して、Amazon DocumentDB の新しいデータベースを作成するときに、復元オペレーションに加えてユーザーロールを再作成する必要があります。

**注記**  
Amazon DocumentDB には、バージョン 100.6.1 までの MongoDB データベースツールをお勧めします。MongoDB データベースツールのダウンロードには、[こちら](https://www.mongodb.com/download-center/database-tools/releases/archive)からアクセスできます。

### 結果の順序
<a name="functional-differences.result-ordering"></a>

Amazon DocumentDB では、結果セットの暗黙的な並べ替え順序は保証されません。結果セットの順序を確実にするには、`sort()` を使用してソート順を明示的に指定します。

次の例では、在庫フィールドに基づいて、インベントリ収集の項目を降順にソートします。

```
db.inventory.find().sort({ stock: -1 })
```

`$sort` 集約ステージを使用する場合は、`$sort` ステージが、集約パイプラインの最後のステージでない限り、並べ替え順序は保持されません。`$sort` 集約ステージと組み合わせた `$group` 集約ステージを使用する場合、`$sort` 集約ステージはおよび `$first` および `$last` アキュムレータにのみ適用されます。Amazon DocumentDB 4.0 では、`$push` のサポートが追加され、前の `$sort` ステージ並べ替え順序を尊重します。

### 再試行可能な書き込み
<a name="functional-differences.retryable-writes"></a>

MongoDB 4.2 互換ドライバーから、再試行可能な書き込みがデフォルトで有効になっています。ただし、Amazon DocumentDB は現在、再試行可能な書き込みをサポートしていません。機能の違いは、次のようなエラーメッセージで示されます。

```
{"ok":0,"errmsg":"Unrecognized field: 'txnNumber'","code":9,"name":"MongoError"} 
```

再試行可能な書き込みは、接続文字列 (例えば、`MongoClient("mongodb://my.mongodb.cluster/db?retryWrites=false")`) または MongoClient コンストラクタのキーワード引数 (例えば、`MongoClient("mongodb://my.mongodb.cluster/db", retryWrites=False)`) で無効にできます。

次に、接続文字列の再試行可能な書き込みを無効にする Python の例を示します。

```
client = pymongo.MongoClient('mongodb://<username>:<password>@docdb-2019-03-17-16-49-12.cluster-ccuszbx3pn5e.us-east-1.docdb.amazonaws.com:27017/?replicaSet=rs0',w='majority',j=True,retryWrites=False) 
```

### スパースインデックス
<a name="functional-differences.sparse-index"></a>

クエリで作成したスパースなインデックスを使用するには、インデックスをカバーするフィールドで `$exists` 句を使用する必要があります。`$exists` を省略した場合、Amazon DocumentDB はスパースなインデックスを使用しません。

以下に例を示します。

```
db.inventory.count({ "stock": { $exists: true }})
```

スパースなマルチキーインデックスの場合、ドキュメントのルックアップによって値のセットが生成され、インデックス付きフィールドのサブセットのみが見つからない場合、Amazon DocumentDB は一意キー制約をサポートしません。例えば、`createIndex({"a.b" : 1 }, { unique : true, sparse :true })` を入力すると、`"a" : [ { "b" : 2 }, { "c" : 1 } ]` がインデックスに格納されているため、`"a.c"` はサポートされません。

### `$all` 式内での `$elemMatch` の使用
<a name="functional-differences.elemMatch"></a>

Amazon DocumentDB は `$elemMatch` 演算子が `$all` 内にある表現の使用をサポートしていません。回避策として、次のように `$and` 演算子を `$elemMatch` で使用できます。

元のオペレーション:

```
db.col.find({
  qty: {
    $all: [
      { "$elemMatch": { part: "xyz", qty: { $lt: 11 } } },
      { "$elemMatch": { num: 40, size: "XL" } }
    ]
  }
})
```

更新されたオペレーション:

```
db.col.find({
  $and: [
    { qty: { "$elemMatch": { part: "xyz", qty: { $lt: 11 } } } },
    { qty: { "$elemMatch": { qty: 40, size: "XL" } } }
  ]
})
```

### フィールド名のドル (\$1) とドット (.)
<a name="functional-differences-dollardot"></a>

Amazon DocumentDB は、ネストされたオブジェクトで in、\$1in、\$1nin、または \$1all を使用した場合の、Dollar(\$1) プレフィックス付きフィールドのクエリをサポートしていません。例えば、Amazon DocumentDB では以下のクエリは有効ではありません。

```
coll.find({"field": {"$all": [{ "$a": 1 }]}})
```

### `$lookup`
<a name="functional-differences.lookup"></a>

Amazon DocumentDB は、等価マッチを実行する機能 (左外部結合など) および相関のないサブクエリをサポートしますが、相関のあるサブクエリはサポートしていません。

#### `$lookup` でインデックスを利用する
<a name="functional-differences.lookup-index"></a>

`$lookup` ステージ演算子で、インデックスを利用できるようになりました 。ユースケースに基づいて、パフォーマンスを最適化するために使用できるインデックス作成アルゴリズムが複数あります。このセクションでは、`$lookup` のさまざまなインデックス作成アルゴリズムについて説明し、ワークロードに最適なオプションを選択するのに役立ちます。

デフォルトでは、Amazon DocumentDB は `allowDiskUse:false` が使用された場合はハッシュアルゴリズムを使用し、`allowDiskUse:true` が使用された場合はソートマージを使用します。

**注記**  
`allowDiskUse` オプションは現在、`find` コマンド向けにはサポートされていません。このオプションは集約の一部としてのみサポートされます。`allowDiskUse:true` で集約フレームワークを使用して、メモリ制限を超える可能性のある大規模なクエリを処理することをお勧めします。

ユースケースによっては、クエリオプティマイザで別のアルゴリズムを使用するように強制することが望ましい場合があります。以下は、`$lookup` の集約演算子を利用できる、さまざまなインデックス作成アルゴリズムの例です。
+ **ネストループ**: 外部コレクションが 1 GB 未満で、外部コレクションのフィールドにインデックスがある場合は、通常、ネストループプランがワークロードに役立ちます。ネスト・ループ・アルゴリズムを使用している場合、説明プランではステージが `NESTED_LOOP_LOOKUP` と表示されます。
+ **ソートマージ**: ソートマージプランは、外部コレクションのルックアップに使用されるフィールドにインデックスがなく、作業データセットがメモリに収まらない場合にワークロードにとって有益です。ソートマージアルゴリズムが使用されている場合、説明プランではステージを `SORT_LOOKUP` と表示されます。
+ **ハッシュ**: 外部コレクションが 1 GB 未満で、作業データセットがメモリに収まる場合は、通常、ハッシュプランがワークロードにとって有益です。ハッシュアルゴリズムが使用されている場合、説明プランはステージを `HASH_LOOKUP` と表示されます。

クエリに対して `explain` を使用することで、`$lookup` 演算子に使用されているインデックス作成アルゴリズムを特定できます。以下に例を示します。

```
db.localCollection.explain().aggregate(
   [ 
      { 
         $lookup: 
            { 
               from: "foreignCollection", 
               localField: "a", 
               foreignField: "b", 
               as: "joined" 
            } 
      } 
   ]
)

output
{
    "queryPlanner" : {
        "plannerVersion" : 1,
        "namespace" : "test.localCollection",
        "winningPlan" : {
            "stage" : "SUBSCAN",
            "inputStage" : {
                "stage" : "SORT_AGGREGATE",
                "inputStage" : {
                    "stage" : "SORT",
                    "inputStage" : {
                        "stage" : "NESTED_LOOP_LOOKUP",
                        "inputStages" : [
                            {
                                "stage" : "COLLSCAN"
                            },
                            {
                                "stage" : "FETCH",
                                "inputStage" : {
                                    "stage" : "COLLSCAN"
                                }
                            }
                        ]
                    }
                }
            }
        }
    },
    "serverInfo" : {
        "host" : "devbox-test",
        "port" : 27317,
        "version" : "3.6.0"
    },
    "ok" : 1
}
```

`explain()` メソッドを使用する代わりに、プロファイラを使用して、`$lookup` 演算子の使用で利用されているアルゴリズムを表示することができます。プロファイラーの詳細については、「[Amazon DocumentDB オペレーションのプロファイリング](profiling.md)」を参照してください。

#### `planHint` を使用​する
<a name="functional-differences.lookup-plan"></a>

クエリオプティマイザで別のインデックス作成アルゴリズムと `$lookup` を強制的に使用する場合、`planHint` を使用できます。これを行うには、集約ステージオプションのコメントを使用して、別のプランを強制します。コメントの構文の例を以下に示します。

```
comment : {
    comment :  "<string>",
    lookupStage : { planHint : "SORT" | "HASH" | "NESTED_LOOP" }
}
```

以下は、`planHint` を使用してクエリオプティマイザに `HASH` インデックスアルゴリズムの使用を強制する例です。

```
db.foo.aggregate(
   [                           
      {   
         $lookup:
            {   
               from: "foo",
               localField: "_id",
               foreignField: "_id",
               as: "joined"
            },
      }
   ]
),
{
   comment : "{ \"lookupStage\" : { \"planHint\": \"HASH\" }}"
```

どのアルゴリズムがワークロードに最適かをテストするには、`executionStats` パラメータにある `explain` メソッドを使用して、`$lookup` ステージの実行時間を測定することができ、これはインデックス作成アルゴリズム (つまり、`HASH` / `SORT`/`NESTED_LOOP`) を変更しながらできます。

次の例は `executionStats` を使用して、`$lookup` ステージの実行時間を測定するには、`SORT` アルゴリズムを使用します。

```
db.foo.explain("executionStats").aggregate(
   [    
      {   
         $lookup:
            {
               from: "foo",
               localField: "_id",
               foreignField: "_id",
               as: "joined"
            },
      }
   ]
),
{
   comment : "{ \"lookupStage\" : { \"planHint\": \"SORT\" }}"
```

### `$natural` および逆順のソート
<a name="functional-differences.natural"></a>

Amazon DocumentDB は、フォワードコレクションスキャンでのみ `$natural` をサポートします。逆順のコレクションスキャン (`{$natural: -1}`) は `MongoServerError` につながります。