No MongoDB 2.0 e anterior, isso não é possível. O que você quer fazer é retornar um elemento específico do array - mas não é isso que sua projeção está realmente fazendo, ela apenas retornará o array inteiro e depois o elemento z de cada um.
No entanto, com o 2.2 (rc2 ao escrever esta resposta), as coisas ficaram um pouco melhores. Agora você pode usar $elemMatch como parte de sua projeção (consulte SERVER-2238 para obter detalhes) para que você recupere apenas o elemento de matriz necessário. Então, tente algo assim:
db.foo.find({"ID":"123",'a':{$elemMatch:{'x':"/"}}},{_id : 0, 'a.$': 1})
//returns
{ "a" : [ { "x" : "/", "y" : "2000", "z" : "1000" } ] }
Ou apenas use $elemMatch na própria projeção, que você pode achar mais limpa:
db.foo.find({"ID":"123"},{_id : 0, 'a':{$elemMatch:{'x':"/"}}})
//returns
{ "a" : [ { "x" : "/", "y" : "2000", "z" : "1000" } ] }
Então, agora, pelo menos a matriz retornada é apenas aquela que contém apenas as entradas que você deseja e você pode simplesmente referenciar o elemento z relevante (as projeções elemMatch em um subdocumento ainda não são suportadas).
Por último, mas não menos importante, em 2.2 temos o framework de agregação, e uma das coisas que ele pode fazer (com o
$project
operador, é remodelar seus documentos e alterar subdocumentos e elementos de matriz em matrizes de nível superior. Para obter o resultado desejado, você faria algo assim:db.foo.aggregate(
{$match : {"ID":"123"}},
{$unwind : "$a"},
{$match : {"a.x":"/"}},
{$project : {_id : 0, z : "$a.z"}}
)
O resultado fica assim:
{ "result" : [ { "z" : "1000" } ], "ok" : 1 }