2011-01-21 25 views
28

Sono stato utile per ottenere il massimo valore su una colonna per un documento mongo. Posso ordinarlo e ottenere il top/bottom, ma sono abbastanza sicuro che c'è un modo migliore per farlo.Ottenere il valore più alto di una colonna in MongoDB

Ho provato quanto segue (e combinazioni diverse):

transactions.find("id" => x).max({"sellprice" => 0}) 

ma mantiene gettando errori. Qual è un buon modo per farlo oltre a ordinare e ottenere il massimo?

Grazie!

+0

È necessario includere gli errori che sta lanciando. –

risposta

48

max() non funziona come previsto in SQL per Mongo. Questo probabilmente cambierà nelle versioni future, ma al momento, max, min devono essere usati con le chiavi indicizzate principalmente internamente per il sharding.

vedere http://www.mongodb.org/display/DOCS/min+and+max+Query+Specifiers

Purtroppo per ora l'unico modo per ottenere il valore massimo è quello di ordinare il disc raccolta su tale valore e prendere la prima.

transactions.find("id" => x).sort({"sellprice" => -1}).limit(1).first() 
+3

Si dovrebbe anche fare. Prima altrimenti si ottiene solo un cursore. –

0

Se la colonna indicizzata quindi una sorta dovrebbe essere OK, assumendo Mongo solo utilizza l'indice per ottenere un insieme ordinato. Altrimenti è più efficiente iterare sulla raccolta, tenendo presente il maggior valore visto. per esempio.

max = nil 
coll.find("id" => x).each do |doc| 
    if max == nil or doc['sellprice'] > max then 
     max = doc['sellprice'] 
    end 
end 

(Mi scuso se il mio Rubino è un po 'Comunque, non ho usato per un lungo periodo di tempo - ma l'approccio generale dovrebbe essere chiaro dal codice.)

+1

Prendere in considerazione l'iterazione con MapReduce !!! Questo perché MongoDB è cool, altrimenti usa file flat ;-) –

0

Supponendo che stavo usando il driver di Ruby (Ho visto un tag mongodb-rubino sul fondo), farei qualcosa di simile al seguente se volessi ottenere il massimo _id (supponendo che il mio _id sia ordinabile). Nella mia implementazione, il mio _id era un numero intero.

result = my_collection.find({}, :sort => ['_id', :desc]).limit(1) 

Per ottenere il minimo _id nella collezione, basta cambiare :desc per :asc

+0

Non sarebbe find_one() essere meglio dell'utilizzo di limit()? 'result = my_collection.find_one ({},: sort => ['_id',: desc])' – Anurag

19

ordinamento potrebbe essere eccessivo. Si può solo fare un gruppo per

db.messages.group(
      {key: { created_at:true }, 
      cond: { active:1 }, 
      reduce: function(obj,prev) { if(prev.cmax<obj.created_at) prev.cmax = obj.created_at; }, 
      initial: { cmax: **any one value** } 
      }); 
+3

Questo è esattamente il modo giusto per farlo con MongoDB! –

+4

Non direi che è eccessivo considerare [questa citazione dal manuale] (http://docs.mongodb.org/manual/reference/operator/aggregation/limit/) * "Quando un ordinamento $ precede immediatamente un limite $ nella pipeline, l'operazione $ sort mantiene solo i primi n risultati man mano che progredisce, dove n è il limite specificato "* – aioobe

3

uso aggregato():

db.transactions.aggregate([ 
    {$match: {id: x}}, 
    {$sort: {sellprice:-1}}, 
    {$limit: 1}, 
    {$project: {sellprice: 1}} 
]); 
8
db.collectionName.aggregate(
    { 
    $group : 
    { 
     _id : "", 
     last : 
     { 
     $max : "$sellprice" 
     } 
    } 
    } 
) 
5

Esempio codice shell MongoDB per gli aggregati di calcolo.

si veda la voce mongodb manuale per gruppo (molte applicazioni) :: http://docs.mongodb.org/manual/reference/aggregation/group/#stage._S_group

In seguito, sostituire la $ vars con la chiave di raccolta e di destinazione variabile.

db.activity.aggregate( 
    { $group : { 
     _id:"$your_collection_key", 
     min: {$min : "$your_target_variable"}, 
     max: {$max : "$your_target_variable"} 
    } 
    } 
) 
0

seguente query fa la stessa cosa: db.student.find({}, {'_id':1}).sort({_id:-1}).limit(1)

Per me, questo risultato seguente prodotto: { "_id" : NumberLong(10934) }

4

Si lavorerà secondo il vostro requisito.

transactions.find("id" => x).sort({"sellprice" => -1}).limit(1).first() 
+1

è meglio aggiungere qualche commento al codice –

Problemi correlati