

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

# Planificateur de requêtes v2
<a name="query-planner"></a>

Le nouveau planificateur de requêtes pour Amazon DocumentDB (planificateur version 2.0) propose des fonctionnalités avancées d'optimisation des requêtes et des performances améliorées. La version 2.0 de Planner pour Amazon DocumentDB 5.0 améliore les performances jusqu'à 10 fois par rapport à la version précédente lors de l'utilisation `find` et des `update` opérateurs utilisant des index. L'amélioration des performances provient principalement de l'utilisation de plans d'index plus optimaux et de l'activation de la prise en charge de l'analyse d'index pour les opérateurs tels que les opérateurs de négation (`$neq`,`$nin`) et les opérateurs imbriqués`$elementMatch`. Les requêtes Planner version 2.0 sont exécutées plus rapidement grâce à de meilleures techniques d'estimation des coûts, à des algorithmes optimisés et à une stabilité accrue. La version 2.0 du planificateur prend également en charge le filtre APIs de cache du plan, ce qui améliore la stabilité du planificateur. Grâce à cette fonctionnalité, Amazon DocumentDB 5.0 permet désormais de sélectionner parmi les différentes versions du planificateur de requêtes.

**Topics**
+ [Conditions préalables](#nqp-prerequisites)
+ [Sélection de la version 2.0 du planificateur comme planificateur de requêtes par défaut](#second-concept-chapter)
+ [Bonnes pratiques](#nqp-best-practices)
+ [Limitations](#nqp-limitations)
+ [Améliorations apportées aux `Update` opérateurs `Find` et aux opérateurs](#operator-improvements)
+ [API de filtre de cache de plan](#plan-cache-filter-api)
+ [Différences de comportement potentielles entre les versions 1.0, 2.0 et MongoDB du planificateur](#planner-behavior-differences)
+ [La version 2.0 de Planner comble les écarts de comportement avec MongoDB](#planner-v2-mongo-gap-bridge)

## Conditions préalables
<a name="nqp-prerequisites"></a>

Les prérequis suivants s'appliquent à la version 2.0 du planificateur :
+ La version 2.0 de Planner est disponible dans toutes les régions où la version 5.0 du moteur est disponible. 
+ Pour choisir d'utiliser la version 2.0 comme planificateur de requêtes par défaut, votre cluster doit utiliser le correctif moteur 3.0.15902 ou une version ultérieure d'Amazon DocumentDB version 5.0. Pour connaître les étapes de mise à jour vers le dernier correctif de version du moteur, consultez[Exécution d'une mise à jour corrective de la version du moteur d'un cluster](db-cluster-version-upgrade.md).
+ Pour définir le planificateur version 2.0 comme planificateur de requêtes par défaut, vous devez disposer des autorisations IAM pour mettre à jour les groupes de paramètres du cluster.
+ Pour Amazon DocumentDB 8.0, le planificateur version 3.0 est le planificateur de requêtes par défaut. Consultez [Planificateur de requêtes v3](query-planner-v3.md) pour plus de détails.

## Sélection de la version 2.0 du planificateur comme planificateur de requêtes par défaut
<a name="second-concept-chapter"></a>

Procédez comme suit pour sélectionner 2.0 comme planificateur de requêtes par défaut depuis la console ou la CLI :
+ Suivez les étapes décrites [Modification des paramètres du cluster Amazon DocumentDB](cluster_parameter_groups-parameters.md) pour modifier le groupe de paramètres de votre cluster.
+ Pour le paramètre intitulé « PlannerVersion », remplacez la valeur par 2.0 pour indiquer la version 2.0 du planificateur.
+ Sélectionnez **Appliquer immédiatement** (sélectionner **Appliquer au redémarrage** rendra la sélection inefficace jusqu'au prochain redémarrage du cluster).

## Bonnes pratiques
<a name="nqp-best-practices"></a>

Pour obtenir les résultats escomptés, appliquez les meilleures pratiques suivantes lors de l'application de la version 2.0 du planificateur :
+ Dans un cluster global, sélectionnez la même `plannerVersion` valeur (1,0 ou 2,0) dans les groupes de paramètres du cluster pour les deux régions. Notez que la sélection de différentes versions du planificateur dans les régions principale et secondaire peut entraîner un comportement et des performances de requête incohérents.
+ La mise à jour vers la version 2.0 du planificateur pendant une période de maintenance planifiée ou pendant des périodes de trafic réduit sera la moins perturbatrice, car le taux d'erreur peut augmenter si la version du planificateur est modifiée alors que les charges de travail sont en cours d'exécution active.
+ La version 2.0 de Planner fonctionne de manière optimale avec le shell MongoDB version 5.0.

## Limitations
<a name="nqp-limitations"></a>

Les limitations suivantes s'appliquent à la version 2.0 du planificateur :
+ La version 2.0 du planificateur n'est pas prise en charge dans les clusters élastiques, qui reviendront à la version 1.0 du planificateur.
+ La version 2.0 du planificateur n'est pas prise en charge pour l'agrégation et les commandes distinctes, qui seront renvoyées à la version 1.0 du planificateur.
+ Les requêtes contenant des expressions régulières, des recherches textuelles, des données géospatiales, des schémas jsonschema ou des filtres ne sont pas prises `$expr` en charge par le filtre de cache de plan dans la version 2.0 du planificateur.

## Améliorations apportées aux `Update` opérateurs `Find` et aux opérateurs
<a name="operator-improvements"></a>

La version 2.0 du planificateur optimise les opérations fondamentales`find`, notamment `update``delete`, et `find-and-modify` les commandes. Les sections à onglets suivantes présentent les fonctionnalités améliorées pour les index, ainsi que les améliorations des performances des requêtes avec la version 2.0 du planificateur :

------
#### [ Enhanced index support ]
+ La version 2.0 de Planner ajoute la prise en charge des index pour les opérateurs de négation `$nin` `$ne``$not {eq}`, notamment`$not {in}`,, et, ainsi que `$type` et`$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 }}}}})
  ```
+  La version 2.0 du planificateur utilise des index épars ou partiels, même lorsqu'ils ne `$exists` sont pas présents dans l'expression de requête.

  ```
  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" })
  ```
+ La version 2.0 de Planner utilisera des index partiels même lorsque la condition de requête ne correspond pas exactement à l'expression du filtre d'index partiel.

  ```
  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}})
  ```
+ La version 2.0 du planificateur utilise une analyse d'index partielle avec des requêtes \$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}}})
  ```
+ La version 2.0 de Planner inclut la prise en charge de l'analyse d'index`$regex`, sans qu'il soit nécessaire de fournir `$hint` le code de votre application. `$regex`prend en charge l'index sur les recherches de préfixes uniquement.

  ```
  Sample Document: { "x": [1, 2, 3], "y": "apple" }
  db.foo.createIndex({ "x": 1, "y": 1 })
  db.foo.find({"y":{ $regex: "^a" }})
  ```
+ La version 2.0 du planificateur améliore les performances des requêtes impliquant des index multiclés, avec des conditions d'égalité sur les champs multiclés.

  ```
  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)
  ```
+ La version 2.0 de Planner améliore les performances des requêtes impliquant plusieurs filtres, en particulier pour les collections contenant des documents de plus de 8 Ko.

  ```
  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}}]})
  ```
+ La version 2.0 de Planner améliore les performances des requêtes lors de l'utilisation de `$in` l'opérateur avec un index composé en éliminant l'étape de tri.

  ```
  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})
  ```

  Il améliore également les performances des requêtes qui utilisent des index multiclés avec `$in` des éléments.

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

------
#### [ Query performance improvements ]
+ La version 2.0 de Planner améliore les performances des requêtes impliquant plusieurs filtres, en particulier pour les collections contenant des documents de plus de 8 Ko.

  ```
  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}}]})
  ```
+ La version 2.0 de Planner améliore les performances des requêtes lors de l'utilisation de `$in` l'opérateur avec un index composé en éliminant l'étape de tri.

  ```
  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})
  ```

  Il améliore également les performances des requêtes qui utilisent des index multiclés avec `$in` des éléments.

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

------

## API de filtre de cache de plan
<a name="plan-cache-filter-api"></a>

**Note**  
L'index de texte n'est pas pris en charge avec le filtre de cache du plan.
+ La version 2.0 de Planner ajoute la prise en charge de la fonctionnalité de filtre d'index qui vous permet de spécifier une liste d'index qu'une forme de requête spécifique peut utiliser. Cette fonctionnalité est accessible via l'API et peut être contrôlée du côté du serveur. Si vous rencontrez une régression de requête, cette fonctionnalité vous offre une option plus rapide et plus flexible pour atténuer le problème sans avoir à modifier le code de votre application.

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

  Pour répertorier tous les filtres de la collection, utilisez la commande suivante :

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

  Cette commande affiche tous les filtres d'index de la collection. Exemple de sortie :

  ```
  {
  "filters" : [
  {
  "query" : {a: "@", b: "@"},
  "sort" : {a: 1},
  "indexes" : [
  <index1>,
  ...
  ]
  },
  ...
  ],
  "ok": 1
  }
  ```
+ Vous pouvez utiliser deux nouveaux champs issus de la sortie de `explain` commande pour analyser le filtrage d'index du planificateur version 2.0 : `indexFilterSet` et`indexFilterApplied`. `indexFilterSet`est défini sur « true » s'il existe un filtre d'index défini sur la collection qui correspond à la forme de la requête. `indexFilterApplied`est défini sur « vrai » si, et uniquement si la requête a appliqué un filtre d'index et choisi un plan utilisant un index dans la liste de filtres.

  Vous pouvez effacer le filtre d'index à l'aide de la commande suivante :

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

  Pour effacer tous les filtres de la collection « foo », utilisez la commande suivante :

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

  Pour effacer une forme de requête spécifique avec n'importe quel type de tri, vous pouvez copier-coller la forme de requête à partir de la sortie de `planCacheListFilters` :

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

  Pour effacer une forme de requête spécifique avec un champ spécifique à trier, vous pouvez copier-coller la forme de requête à partir de la sortie de `planCacheListFilters` :

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

## Différences de comportement potentielles entre les versions 1.0, 2.0 et MongoDB du planificateur
<a name="planner-behavior-differences"></a>

Dans certains cas extrêmes, il est possible que la version 2.0 du planificateur produise des résultats légèrement différents de ceux de MongoDB. Cette section présente quelques exemples de ces possibilités.

------
#### [ \$1(update) and \$1(projection) ]
+ Dans certains cas, `$(projection)` les opérateurs `$(update)` de MongoDB peuvent se comporter différemment de la version 1.0 du planificateur d'Amazon DocumentDB. Voici quelques exemples :

  ```
  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 } }
  ```
  + **Planner version 1.0** — Champ de mises à jour 2022
  + **MongoDB** — Champ de mises à jour 2022
  + **Planner version 2.0** — Champ de mises à jour 2021
+ 

  ```
  db.col.insert({x:[1,2,3]})
  db.col.update({$and:[{x:1},{x:3}]},{$set:{"x.$":500}})
  ```
  + **Planner version 1.0** — Met à jour de manière aléatoire le premier élément correspondant
  + **MongoDB** — Met à jour de manière aléatoire le premier élément correspondant
  + **Planner version 2.0** — Ne fait pas de mises à jour
+ 

  ```
  db.col.insert({x:[1,2,3]})
  db.col.find()
  ```
  + **Planner version 1.0** — Sélectionne aléatoirement l'élément correspondant
  + **MongoDB** — Sélectionne aléatoirement l'élément correspondant
  + **Planner version 2.0** — Ne fait aucune sélection
+ 

  ```
  db.col.insert({x:100})
  db.col.update({x:100},{x:100})
  ```
  + **Planner version 1.0** — Changements de comptage modifiés
  + **MongoDB** — Changements de nombre modifiés
  + **Planner version 2.0** — Le nombre modifié ne change pas lorsqu'il est mis à jour avec la même valeur.
+ Lorsque `$(update)` l'opérateur est utilisé avec`$setOnInsert`, le planificateur version 1.0 et MongoDB génèrent une erreur, mais pas le planificateur version 2.0.
+ Le fait de renommer un champ inexistant `$field` génère une erreur dans le planificateur version 2.0, alors que cela ne produit aucune mise à jour dans le planificateur version 1.0 et MongoDB.

------
#### [ Index behavior ]
+ La version 2.0 du planificateur génère une erreur lorsqu'elle `$hint` est appliquée avec un index inapproprié, contrairement à la version 1.0 du planificateur et à 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`ne peut pas être utilisé `$hint({“$natural”:1})` dans la version 2.0 du planificateur.

  ```
  // 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" }
  ```
+ Alors que MongoDB prend en charge les scans complets des index regex, la version 2.0 du planificateur prend en charge le scan des index regex uniquement sur les champs de préfixes.

  ```
  // 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)
  ```
+ Il existe des différences inhérentes à l'utilisation de filtres de cache de plans avec la version 2.0 du planificateur par rapport à MongoDB. Alors que la version 2.0 du planificateur ne permet pas de spécifier la « projection » et le « classement » avec les filtres de cache du plan, MongoDB le permet. Cependant, le filtre d'index MongoDB est uniquement en mémoire et est perdu après le redémarrage. La version 2.0 du planificateur conserve les filtres d'index lors des redémarrages et des correctifs.

------
#### [ Others ]
+ Le format des journaux d'audit DML lors de l'utilisation de la version 2.0 du planificateur est légèrement différent de celui de la version 1.0 du planificateur.

  ```
  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}}
  ```
+ La condition de l'indice dans le cadre du plan d'explication :

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

  La version 2.0 du planificateur explique la sortie du plan en affichant la condition de l'index et le filtre :

  ```
  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)
  }
  ```

  La version 1.0 du planificateur explique le résultat du plan :

  ```
  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)
  }
  ```

------

## La version 2.0 de Planner comble les écarts de comportement avec MongoDB
<a name="planner-v2-mongo-gap-bridge"></a>

Dans certains domaines, la version 2.0 du planificateur comble les écarts de comportement de MongoDB :
+ La version 2.0 du planificateur permet de rechercher un index numérique sur des tableaux aplatis pour : `$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}}})
  ```
+ Alors que la version 1.0 du planificateur excluait les chaînes dans la projection, le comportement du planificateur version 2.0 s'aligne sur celui de MongoDB et les traite comme des valeurs littérales. »

  ```
  // 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 }
  ```
+ La version 2.0 du planificateur, comme MongoDB, n'autorise pas la projection sur les mêmes champs « x » et « 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 ] }
  ```
+ La version 2.0 du planificateur, comme MongoDB, permet la projection sur des sous-documents : 

  ```
  // 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"
  }
  ```
+ Avec la version 2.0 de Planner, comme MongoDB, la projection ne prend pas en charge les champs situés après l'`$`opérateur :

  ```
  // 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 } ] }
  ```
+ La version 2.0 du planificateur, comme MongoDB, permet d'`$hint`utiliser :

  ```
  // 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 }
  ```