Notez la commande quelques lignes plus bas dans la documentation que vous avez liée :
Cela vous indique que les champs inexistants et les champs définis sur null sont traités spécialement.
Dans l'ordre des documents {} et {a: null} pour être équivalent dans l'ordre de tri, l'algorithme de tri doit considérer que le champ de tri manquant est présent et avoir une valeur de null .
Si vous ajoutez explicitement le champ manquant, juste pour voir à quoi il ressemble, l'ordre a plus de sens.
Le filtre {tag: { $gte: { baz: MinKey() }}} appliqué à {_id: 1, tag: {bar: "BAR"}} compare essentiellement {baz: MinKey()} avec {baz: null, bar: "BAR"} .
Près du haut de la documentation que vous avez liée, il indique que MinKey est inférieur à null , c'est donc le bon ordre.
MODIFIER
En général, l'interrogation est plus efficace lorsque les noms de champs ne sont pas eux-mêmes des données. En termes de base de données tabulaire, quelle colonne contiendrait "baz" ?
Une légère modification du schéma simplifierait ce type de requête. Au lieu de {tagname: tagvalue} , utilisez {k:tagname, v:tagvalue} . Vous pourriez alors indexer tag.k et/ou tag.v , et requête sur tag.k pour trouver tous les documents avec une balise "baz", interroger les balises avec des opérations d'inégalité fonctionnerait de manière plus intuitive.
db.collection.find({"tag.k":{$gte:"baz"}})
Des correspondances exactes pourraient être faites avec elemMatch comme
db.collection.find({tag: {$elemMatch:{k:"baz",v:"BAZ"}}})
Si vous avez vraiment besoin que les documents renvoyés contiennent {tagname: tagvalue} , le $arrayToObject l'opérateur d'agrégation peut le faire :
db.collection.aggregate([
{$match: {
"tag.k": {$gte: "baz"}
}},
{
$addFields: {
tag: {$arrayToObject: [["$tag"]]}
}}
])