Sei sulla buona strada, ma ci sono alcune cose da notare qui, a parte la parte che gli array nidificati (e soprattutto con chiavi anonime) non sono esattamente un ottimo modo per archiviare le cose, ma purché tu conosci costantemente la posizione, allora dovrebbe andare ragionevolmente bene.
C'è una netta differenza tra la corrispondenza di documenti e la corrispondenza di "elementi di un array" . Anche se il tuo valore attuale non corrisponderebbe effettivamente (il tuo valore di ricerca non rientra nei limiti del documento), se il valore fosse effettivamente valido la tua query corrisponde correttamente al "documento" qui, che contiene un elemento corrispondente nell'array.
Il "documento" contiene tutto degli elementi dell'array, anche quelli che non corrispondono, ma la condizione dice il "documento" corrisponde, quindi viene restituito. Se vuoi solo gli "elementi" corrispondenti quindi usa .aggregate()
invece:
db.infos.aggregate([
// Still match the document
{ "$match": {
"info": {
"$elemMatch": { "0": {"$gte": 1399583285000} }
}
}},
// unwind the array for the matched documents
{ "$unwind": "$info" },
// Match only the elements
{ "$match": { "info.0": { "$gte": 1399583285000 } } },
// Group back to the original form if you want
{ "$group": {
"_id": "$_id",
"info": { "$push": "$info" }
}}
])
E questo restituisce solo gli elementi che soddisfano la condizione:
{
"_id" : ObjectId("536c1145e99dc11e65ed07ce"),
"info" : [
[
1399583285000,
20.13
],
[
1399583286000,
20.13
]
]
}
O ovviamente se te ne aspettavi solo uno elemento da abbinare, puoi semplicemente usare la proiezione con .find()
**:
db.infos.find(
{
"info":{
"$elemMatch":{
"0": {
"$gt": 1399583285000
}
}
}
},
{
"info.$": 1
}
)
Ma con un termine come $gt
è probabile che tu ottenga più hit all'interno di un documento, quindi l'approccio aggregato sarà più sicuro considerando che il $
posizionale l'operatore restituirà solo il primo corrispondenza.