

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

# クエリプランナー v2
<a name="query-planner"></a>

Amazon DocumentDB の新しいクエリプランナー (プランナーバージョン 2.0) は、高度なクエリ最適化機能とパフォーマンスの向上を備えています。Amazon DocumentDB 5.0 のプランナーバージョン 2.0 は、インデックスで `find` および `update` 演算子を使用する場合、以前のバージョンと比較して最大 10 倍のパフォーマンスの向上を実現します。パフォーマンスの向上は、主に、より最適なインデックスプランを使用し、否定演算子 (`$neq`、`$nin`) やネストされた `$elementMatch` などの演算子のインデックススキャンサポートを有効にすることによるものです。プランナーバージョン 2.0 クエリは、コスト見積もり手法の向上、アルゴリズムの最適化、安定性の向上により、より高速に実行されます。プランナーバージョン 2.0 では、プランキャッシュフィルター API もサポートされているため、プランナーの安定性が向上します。この機能により、Amazon DocumentDB 5.0 では、さまざまなバージョンのクエリプランナーから選択できるようになりました。

**Topics**
+ [前提条件](#nqp-prerequisites)
+ [デフォルトのクエリプランナーとしてのプランナーバージョン 2.0 の選択](#second-concept-chapter)
+ [ベストプラクティス](#nqp-best-practices)
+ [制限事項](#nqp-limitations)
+ [`Find` および `Update` 演算子の改善](#operator-improvements)
+ [プランキャッシュフィルター API](#plan-cache-filter-api)
+ [プランナーバージョン 1.0、2.0、および MongoDB の潜在的な動作の違い](#planner-behavior-differences)
+ [プランナーバージョン 2.0 が MongoDB の動作ギャップを埋める](#planner-v2-mongo-gap-bridge)

## 前提条件
<a name="nqp-prerequisites"></a>

プランナーバージョン 2.0 には、次の前提条件が適用されます。
+ プランナーバージョン 2.0 は、エンジンバージョン 5.0 が利用可能なすべてのリージョンで使用できます。
+ デフォルトのクエリプランナーとしてバージョン 2.0 を使用することを選択するには、クラスターが Amazon DocumentDB バージョン 5.0 のエンジンパッチバージョン 3.0.15902 以降である必要があります。最新のエンジンバージョンパッチに更新する手順については、「[クラスターのエンジンバージョンへのパッチ更新の実行](db-cluster-version-upgrade.md)」を参照してください。
+ プランナーバージョン 2.0 をデフォルトのクエリプランナーとして設定するには、クラスターパラメータグループを更新するための IAM アクセス許可が必要です。
+ Amazon DocumentDB 8.0 では、プランナーバージョン 3.0 がデフォルトのクエリプランナーです。詳細については、「[クエリプランナー v3](query-planner-v3.md)」を参照してください。

## デフォルトのクエリプランナーとしてのプランナーバージョン 2.0 の選択
<a name="second-concept-chapter"></a>

コンソールまたは CLI からデフォルトのクエリプランナーとして 2.0 を選択するには、次の手順に従います。
+ 「[Amazon DocumentDB クラスターパラメータを変更する](cluster_parameter_groups-parameters.md)」の手順に従って、クラスターのパラメータグループを変更します。
+ 「plannerVersion」というタイトルのパラメータの場合、プランナーバージョン 2.0 を示す値を 2.0 に変更します。
+ **[すぐに適用]** を選択します (**[再起動時に適用]** を選択すると、クラスターの次回の再起動まで選択が無効になります)。

## ベストプラクティス
<a name="nqp-best-practices"></a>

期待される結果を得るには、プランナーバージョン 2.0 を適用するときに次のベストプラクティスを使用します。
+ グローバルクラスターで、両方のリージョンのクラスターパラメータグループで同じ `plannerVersion` 値 (1.0 または 2.0) を選択します。プライマリリージョンとセカンダリリージョンで異なるプランナーバージョンを選択すると、クエリの動作とパフォーマンスに一貫性がなくなる可能性があることに注意してください。
+ スケジュールされたメンテナンスウィンドウ中またはトラフィックの減少期間中にプランナーバージョン 2.0 を更新すると、ワークロードがアクティブに実行されているときにプランナーバージョンが変更されるとエラー率が高くなる可能性があるため、中断が最も少なくなります。
+ プランナーバージョン 2.0 は、MongoDB シェルバージョン 5.0 で最も最適に動作します。

## 制限事項
<a name="nqp-limitations"></a>

プランナーバージョン 2.0 には、以下の制限が適用されます。
+ プランナーバージョン 2.0 は、プランナーバージョン 1.0 にフォールバックされるエラスティッククラスターではサポートされていません。
+ プランナーバージョン 2.0 は、集約コマンドと distinct コマンドではサポートされていません。これらはプランナーバージョン 1.0 にフォールバックされます。
+ 正規表現、テキスト検索、地理空間、jsonschema、または `$expr` フィルターを含むクエリは、プランナーバージョン 2.0 のプランキャッシュフィルターではサポートされていません。

## `Find` および `Update` 演算子の改善
<a name="operator-improvements"></a>

プランナーバージョン 2.0 は、`find`、`update`、`delete`、および `find-and-modify` コマンドなどの基本的なオペレーションを最適化します。以下のタブ付きセクションでは、インデックスの拡張機能と、プランナーバージョン 2.0 でのクエリパフォーマンスの向上を示しています。

------
#### [ Enhanced index support ]
+ プランナーバージョン 2.0 では、`$nin`、`$ne`、`$not {eq}`、`$not {in}` などの否定演算子と、`$type` および `$elemMatch` のインデックスサポートが追加されています。

  ```
  Sample Document: { "x": 10, "y": [1, 2, 3] }
  
  db.foo.createIndex({ "x": 1, "y": 1 })
  db.foo.find({ "x": {$nin: [20, 30] }})
  db.foo.find({"x":{ $type: "string" }})
  
  db.foo.createIndex({"x.y": 1})
  db.foo.find({"x":{$elemMatch:{"y":{$elemMatch:{"$gt": 3 }}}}})
  ```
+  プランナーバージョン 2.0 は、クエリ式に `$exists` が存在しない場合でも、スパースインデックスまたは部分インデックスを使用します。

  ```
  Sample Document: {"name": "Bob", "email": "example@fake.com" }
  
  Using Planner Version 1.0, you can specify the command as shown below:
  db.foo.find({email: "example@fake.com", email: {$exists: true}})
  
  Using Planner Version 2.0, you can specify command without $exists:
  db.foo.find({ email: "example@fake.com" })
  ```
+ プランナーバージョン 2.0 では、クエリ条件が部分インデックスフィルター式と完全に一致しない場合でも、部分インデックスが使用されます。

  ```
  Sample Document: {"name": "Bob", "age": 34}
  db.foo.createIndex({"age":1},{partialFilterExpression:{"age":{$lt:50}}})
  
  With Planner Version 1.0, index is used only when the query condition meets the partial
   index filter criterion:
       db.foo.find({"age":{$lt:50}})
  
  With Planner Version 2.0, index is used even when the query condition doesn’t meet the index
  criterion:
  db.foo.find({"age":{$lt:30}})
  ```
+ プランナーバージョン 2.0 では、\$1elemMatch クエリで部分インデックススキャンを使用します。

  ```
  Sample Document: {"name": "Bob", "age": [34,35,36]}
  db.foo.createIndex({"age":1},{partialFilterExpression:{"age":{$lt:50,$gt:20}}})
  db.foo.find({age:{$elemMatch:{$lt:50,$gt:20}}})
  ```
+ プランナーバージョン 2.0 には、アプリケーションコードで `$hint` を指定することなく、`$regex` のインデックススキャンサポートが含まれています。`$regex` はプレフィックス検索でのみインデックスをサポートします。

  ```
  Sample Document: { "x": [1, 2, 3], "y": "apple" }
  db.foo.createIndex({ "x": 1, "y": 1 })
  db.foo.find({"y":{ $regex: "^a" }})
  ```
+ プランナーバージョン 2.0 では、マルチキーフィールドの等価条件を使用して、マルチキーインデックスを含むクエリのパフォーマンスが向上します。

  ```
  Sample Document: {"x": [1, 2, 3],
  "y": 5}
  db.foo.createIndex({"x": 1, "y":1})
  db.foo.find({"x": 2,
  "y": {$gt: 1}}).limit(1)
  ```
+ プランナーバージョン 2.0 では、特に 8 KB を超えるドキュメントを含むコレクションで、複数のフィルターを含むクエリのパフォーマンスが向上します。

  ```
  Sample Document: {"x": 2,
  "y": 4,
  "z": 9,
  "t": 99}
  db.foo.find({$and: [{"x": {$gt : 1}, "y": {$gt : 3}, "z": {$lt : 10},
  "t":{$lt : 100}}]})
  ```
+ プランナーバージョン 2.0 では、ソートステージを削除することで、複合インデックスで `$in` 演算子を使用する場合のクエリのパフォーマンスが向上します。

  ```
  Sample Document: {"x": 2,
  "y": 4,
  "z": 9,
  "t": 99}
  db.foo.createIndex({"x":1, "y":1})
  db.foo.find({"x":2,
  "y":$in:[1,2,3,4]}).sort({x:1,y:1})
  ```

  また、 `$in`要素でマルチキーインデックスを使用するクエリのパフォーマンスも向上します。

  ```
  Sample Document: {"x": [1, 2, 3]}
  db.foo.createIndex({"x": 1})
  db.foo.find("x":{$in:[>100 elements]})
  ```

------
#### [ Query performance improvements ]
+ プランナーバージョン 2.0 では、特に 8 KB を超えるドキュメントを含むコレクションで、複数のフィルターを含むクエリのパフォーマンスが向上します。

  ```
  Sample Document: {"x": 2,
  "y": 4,
  "z": 9,
  "t": 99}
  db.foo.find({$and: [{"x": {$gt : 1}, "y": {$gt : 3}, "z": {$lt : 10},
  "t":{$lt : 100}}]})
  ```
+ プランナーバージョン 2.0 では、ソートステージを削除することで、複合インデックスで `$in` 演算子を使用する場合のクエリのパフォーマンスが向上します。

  ```
  Sample Document: {"x": 2,
  "y": 4,
  "z": 9,
  "t": 99}
  db.foo.createIndex({"x":1, "y":1})
  db.foo.find({"x":2,
  "y":$in:[1,2,3,4]}).sort({x:1,y:1})
  ```

  また、`$in` 要素でマルチキーインデックスを使用するクエリのパフォーマンスも向上します。

  ```
  Sample Document: {"x": [1, 2, 3]}
  db.foo.createIndex({"x": 1})
  db.foo.find("x":{$in:[>100 elements]})
  ```

------

## プランキャッシュフィルター API
<a name="plan-cache-filter-api"></a>

**注記**  
テキストインデックスは、プランキャッシュフィルターではサポートされていません。
+ プランナーバージョン 2.0 では、特定のクエリシェイプで使用できるインデックスのリストを指定できるインデックスフィルター機能のサポートが追加されました。この機能は API からアクセスでき、サーバー側から制御できます。クエリのリグレッションが発生した場合、この機能を使用すると、アプリケーションコードを変更することなく、より迅速かつ柔軟に問題を軽減できます。

  ```
  db.runCommand({ planCacheSetFilter: <collection>, query: <query>,
  sort: <sort>, // optional, 
  indexes: [ <index1>, <index2>, ...],
  comment: <any> // optional})
  ```

  コレクション上のすべてのフィルターを一覧表示するには、次のコマンドを使用します。

  ```
  db.runCommand(
  {
  planCacheListFilters: <collection>
  }
  )
  ```

  このコマンドは、コレクション上のすべてのインデックスフィルターを表示します。出力例:

  ```
  {
  "filters" : [
  {
  "query" : {a: "@", b: "@"},
  "sort" : {a: 1},
  "indexes" : [
  <index1>,
  ...
  ]
  },
  ...
  ],
  "ok": 1
  }
  ```
+ `explain` コマンド出力の 2 つの新しいフィールドを使用して、プランナーバージョン 2.0 のインデックスフィルタリングを分析できます: `indexFilterSet` と `indexFilterApplied`。 `indexFilterSet` は、クエリシェイプに一致するインデックスフィルターがコレクションに設定されている場合は「true」に設定されます。 `indexFilterApplied` は、クエリがインデックスフィルターを適用し、フィルターリストのインデックスを使用してプランを選択した場合にのみ「true」に設定されます。

  次のコマンドを使用して、インデックスフィルターをクリアできます。

  ```
  db.runCommand(
  {
  planCacheClearFilters: <collection>>
  query: <query pattern>, // optional
  sort: <sort specification>, // optional
  comment: <any>. //optional
  }
  )
  ```

  コレクション「foo」のすべてのフィルターをクリアするには、次のコマンドを使用します。

  ```
  db.runCommand({planCacheClearFilters: "foo"})
  ```

  任意のソートで特定のクエリシェイプをクリアするには、`planCacheListFilters` の出力からクエリシェイプをコピーして貼り付けます。

  ```
  db.runCommand({planCacheClearFilters: "foo", query: {a: @}})
  ```

  ソートするフィールドを指定して特定のクエリシェイプをクリアするには、`planCacheListFilters` の出力からクエリシェイプをコピーして貼り付けます。

  ```
  db.runCommand({planCacheClearFilters: "foo", query: {a: @},sort: {a: 1}})
  ```

## プランナーバージョン 1.0、2.0、および MongoDB の潜在的な動作の違い
<a name="planner-behavior-differences"></a>

エッジケースによっては、プランナーバージョン 2.0 が MongoDB の結果とわずかに異なる結果を生成する可能性があります。このセクションでは、これらの可能性の例をいくつか説明します。

------
#### [ \$1(update) and \$1(projection) ]
+ 場合によっては、MongoDB の `$(update)` および `$(projection)` 演算子が Amazon DocumentDB のプランナーバージョン 1.0 とは異なる動作をすることがあります。以下に一部の例を示します。

  ```
  db.students_list.insertMany( [ { _id: 5, student_ids: [ 100, 200 ], grades: [ 95, 100 ], grad_year: [ 2024, 2023 ] } ] )
  ```

  ```
  db.students_list.updateOne({ student_ids: 100, grades: 100, grad_year: 2024 },
  { $set: { “grad_year.$”: 2025 } }
  ```
  + **プランナーバージョン 1.0** — フィールドを更新 2022
  + **MongoDB** — フィールドを更新 2022
  + **プランナーバージョン 2.0** — フィールドを更新 2021
+ 

  ```
  db.col.insert({x:[1,2,3]})
  db.col.update({$and:[{x:1},{x:3}]},{$set:{"x.$":500}})
  ```
  + **プランナーバージョン 1.0** — 一致する最初の要素をランダムに更新
  + **MongoDB** — 一致した最初の要素をランダムに更新
  + **プランナーバージョン 2.0** — 更新を行わない
+ 

  ```
  db.col.insert({x:[1,2,3]})
  db.col.find()
  ```
  + **プランナーバージョン 1.0** — 一致する要素をランダムに選択
  + **MongoDB** — 一致した要素をランダムに選択
  + **プランナーバージョン 2.0** — 選択しない
+ 

  ```
  db.col.insert({x:100})
  db.col.update({x:100},{x:100})
  ```
  + **プランナーバージョン 1.0** — nModified カウントの変更
  + **MongoDB** — nModified カウントの変更
  + **プランナーバージョン 2.0** — nModified カウントは、同じ値で更新しても変更されない。
+ `$(update)` 演算子を `$setOnInsert` で使用すると、プランナーバージョン 1.0 と MongoDB はエラーをスローしますが、プランナーバージョン 2.0 はスローしません。
+ 存在しないフィールドの名前を `$field` に変更すると、プランナーバージョン 2.0 ではエラーがスローされますが、プランナーバージョン 1.0 および MongoDB では更新は生成されません。

------
#### [ Index behavior ]
+ `$hint` が不適切なインデックスで適用されると、プランナーバージョン 2.0 はエラーをスローしますが、プランナーバージョン 1.0 と MongoDB はスローしません。

  ```
  // Insert
  db.col.insert({x:1})
  db.col.insert({x:2})
  db.col.insert({x:3})
  
  // Create index on x with partialFilter Expression {x:{$gt:2}}
  db.col.createIndex({x:1},{partialFilterExpression:{x:{$gt:2}}})
  
  // Mongodb allows hint on the following queries
  db.col.find({x:1}).hint("x_1")
  // result is no documents returned because {x:1} is not indexed by the partial index
  // Without $hint mongo should return {x:1}, thus the difference in result between COLSCAN and IXSCAN
  
  DocumentDB will error out when $hint is applied on such cases.
  db.col.find({x:1}).hint("x_1")
  Error: error: {
      "ok" : 0,
      "operationTime" : Timestamp(1746473021, 1),
      "code" : 2,
      "errmsg" : "Cannot use Hint for this Query. Index is multi key index , partial index or sparse index and query is not optimized to use this index."
  }
  
  rs0:PRIMARY> db.runCommand({"planCacheSetFilter": "col", "query": { location: {$nearSphere: {$geometry: {type: "Point", coordinates: [1, 1]}}}}, "indexes": ["name_1"]})
  {
      "ok" : 0,
      "operationTime" : Timestamp(1750815778, 1),
      "code" : 303,
      "errmsg" : "Unsupported query shape for index filter $nearSphere"
  }
  ```
+ `$near` は、プランナーバージョン 2.0 では `$hint({“$natural”:1})` を使用できません。

  ```
  // indexes present are index on x and geo index
  
  rs0:PRIMARY> db.usarestaurants.getIndexes()
  [
      {
          "v" : 4,
          "key" : {
              "_id" : 1
          },
          "name" : "_id_",
          "ns" : "test.usarestaurants"
      },
      {
          "v" : 4,
          "key" : {
              "location" : "2dsphere"
          },
          "name" : "location_2dsphere",
          "ns" : "test.usarestaurants",
          "2dsphereIndexVersion" : 1
      }
  ]
  
  // Planner Version 2.0 will throw an error when $hint is applied with index "x_1"
  rs0:PRIMARY> db.usarestaurants.find({    "location":{       "$nearSphere":{          "$geometry":{             "type":"Point",             "coordinates":[                -122.3516,                47.6156             ]          },          "$minDistance":1,          "$maxDistance":2000       }    } }, {    "name":1 }).hint({"$natural": 1})
  Error: error: {
      "ok" : 0,
      "operationTime" : Timestamp(1746475524, 1),
      "code" : 291,
      "errmsg" : "unable to find index for $geoNear query"
  }
  
  // Planner Version 1.0 and MongoDB will not throw an error
   db.usarestaurants.find({    "location":{       "$nearSphere":{          "$geometry":{             "type":"Point",             "coordinates":[                -122.3516,                47.6156             ]          },          "$minDistance":1,          "$maxDistance":2000       }    } }, {    "name":1 }).hint({"$natural": 1})
  { "_id" : ObjectId("681918e087dadfd99b7f0172"), "name" : "Noodle House" }
  ```
+ MongoDB は完全な正規表現インデックススキャンをサポートしていますが、プランナーバージョン 2.0 はプレフィックスフィールドでのみ正規表現インデックススキャンをサポートしています。

  ```
  // index on x
  db.col.createIndex({x:1})
  
  // index scan is used only for prefix regexes
  rs0:PRIMARY> db.col.find({x: /^x/}).explain()
  {
      "queryPlanner" : {
          "plannerVersion" : 2,
          "namespace" : "test.col",
          "winningPlan" : {
              "stage" : "IXSCAN",
              "indexName" : "x_1",
              "direction" : "forward",
              "indexCond" : {
                  "$and" : [
                      {
                          "x" : {
                              "$regex" : /^x/
                          }
                      }
                  ]
              },
              "filter" : {
                  "x" : {
                      "$regex" : /^x/
                  }
              }
          }
      },
      "indexFilterSet" : false,
      "indexFilterApplied" : false,
      "ok" : 1,
      "operationTime" : Timestamp(1746474527, 1)
  }
  
  // COLSCAN is used for non-prefix regexes
  rs0:PRIMARY> db.col.find({x: /x$/}).explain()
  {
      "queryPlanner" : {
          "plannerVersion" : 2,
          "namespace" : "test.col",
          "winningPlan" : {
              "stage" : "COLLSCAN",
              "filter" : {
                  "x" : {
                      "$regex" : /x$/
                  }
              }
          }
      },
      "indexFilterSet" : false,
      "indexFilterApplied" : false,
      "ok" : 1,
      "operationTime" : Timestamp(1746474575, 1)
  ```
+ プランナーバージョン 2.0 でのプランキャッシュフィルターの使用には、MongoDB と固有の違いがあります。プランナーバージョン 2.0 では、プランキャッシュフィルターとの「射影」と「照合」の指定はサポートされていませんが、MongoDB はサポートしています。ただし、MongoDB インデックスフィルターはインメモリのみであり、再起動後に失われます。プランナーバージョン 2.0 は、再起動とパッチを通じてインデックスフィルターを保持します。

------
#### [ Others ]
+ プランナーバージョン 2.0 を使用する場合の DML 監査ログの形式は、プランナーバージョン 1.0 の形式と若干異なります。

  ```
  command -  db.col.find({x:1})
  
  ************** Audit logs generated ******************
  
  // v1 format for dml audit logs
  {"atype":"authCheck","ts":1746473479983,"timestamp_utc":"2025-05-05 19:31:19.983","remote_ip":"127.0.0.1:47022","users":[{"user":"serviceadmin","db":"test"}],"param":{"command":"find","ns":"test.col","args":{"batchSize":101,"filter":{"x":1},"find":"col","limit":18446744073709551615,"lsid":{"id":{"$binary":"P6RCGz9ZS4iWBSSHWXW15A==","$type":"4"},"uid":{"$binary":"6Jo8PisnEi3dte03+pJFjdCyn/5cGQL8V2KqaoWsnk8=","$type":"0"}},"maxScan":18446744073709551615,"singleBatch":false,"skip":0,"startTransaction":false},"result":0}}
  
  // v2 formal for dml audit logs
  {"atype":"authCheck","ts":1746473583711,"timestamp_utc":"2025-05-05 19:33:03.711","remote_ip":"127.0.0.1:37754","users":[{"user":"serviceadmin","db":"test"}],"param":{"command":"find","ns":"test.col","args":{"find":"col","filter":{"x":1},"lsid":{"id":{"$binary":"nJ88TGCSSd+BeD2+ZtrhQg==","$type":"4"}},"$db":"test"},"result":0}}
  ```
+ 説明プランの一部としてのインデックス条件:

  ```
  rs0:PRIMARY> db.col.createIndex({index1:1})
  {
  	"createdCollectionAutomatically" : false,
  	"numIndexesBefore" : 1,
  	"numIndexesAfter" : 2,
  	"ok" : 1,
  	"operationTime" : Timestamp(1761149251, 1)
  }
  ```

  インデックス条件とフィルターを表示するプランナーバージョン 2.0 の説明プラン出力:

  ```
  rs0:PRIMARY> db.col.find({$and:[{price:{$eq:300}},{item:{$eq:"apples"}}]}).explain()
  {
  	"queryPlanner" : {
  		"plannerVersion" : 2,
  		"namespace" : "test.col",
  		"winningPlan" : {
  			"stage" : "IXSCAN",
  			"indexName" : "price_1",
  			"direction" : "forward",
  			"indexCond" : {
  				"$and" : [
  					{
  						"price" : {
  							"$eq" : 300
  						}
  					}
  				]
  			},
  			"filter" : {
  				"$and" : [
  					{
  						"item" : {
  							"$eq" : "apples"
  						}
  					}
  				]
  			}
  		}
  	},
  	"indexFilterSet" : false,
  	"indexFilterApplied" : false,
  	"ok" : 1,
  	"operationTime" : Timestamp(1761149497, 1)
  }
  ```

  プランナーバージョン 1.0 の説明プラン出力:

  ```
  rs0:PRIMARY> db.col.find({$and:[{price:{$eq:300}},{item:{$eq:"apples"}}]}).explain()
  {
  	"queryPlanner" : {
  		"plannerVersion" : 1,
  		"namespace" : "test.col",
  		"winningPlan" : {
  			"stage" : "IXSCAN",
  			"indexName" : "price_1",
  			"direction" : "forward"
  		}
  	},
  	"ok" : 1,
  	"operationTime" : Timestamp(1761149533, 1)
  }
  ```

------

## プランナーバージョン 2.0 が MongoDB の動作ギャップを埋める
<a name="planner-v2-mongo-gap-bridge"></a>

プランナーバージョン 2.0 が MongoDB の動作ギャップを埋める領域がいくつかあります。
+ プランナーバージョン 2.0 では、`$elemMatch` のフラット化された配列で数値インデックスルックアップが許可されます。

  ```
  doc: {"x" : [ [ { "y" : 1 } ] ] }
  
  // Planner Version 2 and mongo
  > db.bar.find({"x.0": {$elemMatch: {y: 1}}})
  { "_id" : ObjectId("68192947945e5846634c455a"), "x" : [ [ { "y" : 1 } ] ] }
  > db.bar.find({"x": {$elemMatch: {"0.y": 1}}})
  { "_id" : ObjectId("68192947945e5846634c455a"), "x" : [ [ { "y" : 1 } ] ] }
  
  //Whereas Planner Version 1 wouldn't return any results.
  > db.bar.find({"x.0": {$elemMatch: {y: 1}}})
  > db.bar.find({"x": {$elemMatch: {"0.y": 1}}})
  ```
+ プランナーバージョン 1.0 は射影で文字列を除外しましたが、プランナーバージョン 2.0 の動作は MongoDB と一致し、リテラル値として扱います

  ```
  // Planner V2/ MongoDB
  > db.col.find()
  { "_id" : ObjectId("681537738aa101903ed2fe05"), "x" : 1, "y" : 1 }
  > db.col.find({},{x:"string"})
  { "_id" : ObjectId("681537738aa101903ed2fe05"), "x" : "string" }
  
  // Planner V1 treats strings as exclude in projection
  rs0:PRIMARY> db.col.find()
  { "_id" : ObjectId("68153744d42969f11d5cca72"), "x" : 1, "y" : 1 }
  rs0:PRIMARY> db.col.find({},{x:"string"})
  { "_id" : ObjectId("68153744d42969f11d5cca72"), "y" : 1 }
  ```
+ MongoDB と同様に、プランナーバージョン 2.0 では、同じフィールド「x」と「x.a」での射影は許可されません。

  ```
  // Planner version 2/MongoDB will error out
  > db.col.find()
  { "_id" : ObjectId("68153da2012265816bc9ba23"), "x" : [ { "a" : 1 }, 3 ] }
   db.col.find({},{"x.a":1,"x":1}) // error
   
  // Planner Version 1 does not error out
  db.col.find()
  { "_id" : ObjectId("68153da2012265816bc9ba23"), "x" : [ { "a" : 1 }, 3 ] }
  
  db.col.find({},{"x.a":1,"x":1})
  { "_id" : ObjectId("68153d60143af947c720d099"), "x" : [ { "a" : 1 }, 3 ] }
  ```
+ MongoDB と同様に、プランナーバージョン 2.0 では、サブドキュメントへの射影が許可されます。

  ```
  // Planner Version2/MongoDB supports projections on subdocuments
   db.col.find()
  { "_id" : ObjectId("681542d8f35ace71f0a50004"), "x" : [ { "y" : 100 } ] }
  > db.col.find({},{"x":{"y":1}})
  { "_id" : ObjectId("681542b7a22d548e4ac9ddea"), "x" : [ { "y" : 100 } ] }
  
  // Planner V1 throws error if projection is subdocument
   db.col.find()
  { "_id" : ObjectId("681542d8f35ace71f0a50004"), "x" : [ { "y" : 100 } ] }
  rs0:PRIMARY> db.col.find({},{"x":{"y":1}})
  Error: error: {
      "ok" : 0,
      "operationTime" : Timestamp(1746223914, 1),
      "code" : 2,
      "errmsg" : "Unknown projection operator y"
  }
  ```
+ MongoDB などのプランナーバージョン 2.0 では、射影は `$` 演算子の後のフィールドをサポートしていません。

  ```
  // Mongo and Planner Version 2 will error out
    db.col.find()
  { "_id" : ObjectId("68155fa812f843439b593f3f"), "x" : [ { "a" : 100 } ] }
   db.col.find({"x.a":100},{"x.$.a":1}) - // error
   
  // v1 will not error out 
   db.col.find()
  { "_id" : ObjectId("68155fa812f843439b593f3f"), "x" : [ { "a" : 100 } ] }
  db.col.find({"x.a":100},{"x.$.a":1})
  { "_id" : ObjectId("68155dee13b051d58239cd0a"), "x" : [ { "a" : 100 } ] }
  ```
+ MongoDB などのプランナーバージョン 2.0 では、次の `$hint` の使用が許可されます。

  ```
  // v1 will error out on $hint if there are no filters
  db.col.find({}).hint("x_1")
  Error: error: {
      "ok" : 0,
      "operationTime" : Timestamp(1746466616, 1),
      "code" : 2,
      "errmsg" : "Cannot use Hint for this Query. Index is multi key index , partial index or sparse index and query is not optimized to use this index."
  }
  
  
  // Mongo and Planner Version 2 will allow $hint usage
   db.col.find({}).hint("x_1")
  { "_id" : ObjectId("6818f790d5ba9359d68169cf"), "x" : 1 }
  ```