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"]]}
}}
])