2014-03-01 4 views
50

Ich versuche, ein Element aus einer Mongo-Sammlung abzurufen, das mit dem größten _id-Feld. Ich weiß, das durch die Abfrage durchgeführt werden kann:Verwenden von findOne in mongodb, um Element mit maximaler ID zu erhalten

db.collection.find().sort({_id: -1}).limit(1) 

Aber es ist eine Art scheint unelegant und ich habe mich gefragt, ob es eine Möglichkeit gibt, dass bestimmte Element mit FindOne()

Hinweis zu bekommen: ich tun möchte, Dies, weil die ersten Bytes, die ich in ObjectId gelesen habe, den Millisekunden seit der Epoche entsprechen und somit das letzte Element, das eingefügt wird, die größte _id haben wird. Gibt es eine andere Möglichkeit, das letzte in eine Sammlung eingefügte Element abzurufen?

+4

Es gibt nichts unelegant über Ihre ursprüngliche Methode, eigentlich. – JohnnyHK

+1

Denken Sie daran, dass die 'ObjectId' normalerweise vom Client-Treiber erstellt wird, daher ist sie nur so genau/zuverlässig wie die verwendeten Clients. Wenn zwei Treiber in derselben Sekunde eingefügt werden, sind die Ergebnisse nicht vorhersehbar. – WiredPrairie

Antwort

74

sollten Sie find verwenden, wie Sie bereits sind, und nicht Aggregation, die langsamer zu sein, da es die max, um herauszufinden, braucht alle die Werte von _id Felder zu scannen.

Wie Kommentare darauf hingewiesen, gibt es keine Unterschied zwischen der Verwendung von find() und findOne() - funktional oder Eleganz-weise. In der Tat, findOne in der Shell (und in den Treibern, die es implementieren) wird in Bezug auf die Suche definiert (mit Limit -1 und mit hübschen Druck in der Shell).

Wenn Sie wirklich das Äquivalent von

db.collection.find().sort({_id:-1}).limit(1).pretty() 

als findOne tun möchten, können Sie es mit dieser Syntax zu tun:

db.collection.findOne({$query:{},$orderby:{_id:-1}}) 
+1

Vielen Dank für Ihre Antwort! Ich habe erwartet, dass es eine bessere Implementierung für meine Anfrage geben würde, als das Finden von findOne einfach nur ein Ergebnis, aber wenn findOne einfach ein eleganter Fund ist, denke ich, dass es keinen Unterschied gibt. – Jorge

+1

korrekt. und Aggregation (die Sie als richtige Antwort akzeptiert haben) ist eigentlich eine sehr falsche Antwort, weil sie * alle * _id-Werte scannt, wobei find den _id-Index verwendet, um nur einen einzigen Wert zu scannen. –

+0

Der Operator '$ orderby' ist [veraltet seit Version 3.2] (https://docs.mongodb.com/manual/reference/operator/meta/orderby/). Verwenden Sie stattdessen 'cursor.sort()'. – Vadim

8

Sie können max _id mit Aggregation von mongodb erhalten. Suchen und Sortieren kann übertrieben sein.

db.myCollection.aggregate({ 
    $group: { 
     _id: '', 
     last: { 
      $max: "$_id" 
     } 
    } 
}); 
+5

Wie ist das eleganter als find()? Es wird nie schneller und in den meisten Fällen viel langsamer sein. –

+2

in der Tat ist es nicht zu finden und zu sortieren - find mit Sortierung verwendet einen Index, um sofort einen einzelnen Wert auszuwählen. Ihre Aggregationsantwort müsste den gesamten Wertebereich abtasten). –

+3

[Zitat benötigt] – joeytwiddle

1

mit PHP-Treiber (mongodb)
mit findOne()

$filter=[]; 
$options = ['sort' => ['_id' => -1]]; // -1 is for DESC 
$result = $collection->findOne(filter, $options); 
$maxAge = $result['age'] 
-1
$maxId=""; 

$Cursor =$collection->find(); 

foreach($cursor as $document) { 
    $maxid =max($arr=(array($document['id']))); 
} 

print_r($maxid+1); 
Verwandte Themen