Este é um tema realmente confuso. Eu trabalho na 10gen e tive que passar um tempo pensando nisso;)
Vamos ver como o mecanismo de consulta processa essa consulta.
Aqui está a consulta novamente:
> db.test.find({ b : { $gt : 4, $lt : 6}});
Quando chega ao registro que parece que não deveria corresponder...
{ "_id" : ObjectId("4d54cff54364000000004331"), "a" : 1, "b" : [ 2, 4, 6, 8 ] }
A correspondência não é realizada em relação a cada elemento do array, mas sim ao array como um todo.
A comparação é realizada em três etapas:
Etapa 1 :Encontre todos os documentos onde b tem um valor maior que 4
b:[2,4,6,8] corresponde porque 6 e 8 são maiores que 4
Etapa 2 :Encontre todos os documentos onde b tem um valor menor que 6
b:[2,4,6,8] corresponde porque 2 e 4 são menores que 6
Etapa 3 :encontre o conjunto de documentos que correspondeu nas etapas 1 e 2.
O documento com b:[2,4,6,8] correspondeu às duas etapas 1 e 2, portanto, é retornado como uma correspondência. Observe que os resultados também são desduplicados nesta etapa, portanto, o mesmo documento não será retornado duas vezes.
Se você deseja que sua consulta seja aplicada aos elementos individuais da matriz, em vez da matriz como um todo, você pode usar o operador $elemMatch. Por exemplo
> db.temp.find({b: {$elemMatch: {$gt: 4, $lt: 5}}})
> db.temp.find({b: {$elemMatch: {$gte: 4, $lt: 5}}})
{ "_id" : ObjectId("4d558b6f4f0b1e2141b66660"), "b" : [ 2, 3, 4, 5, 6 ] }