Obtenez le dernier enregistrement de la collection mongodb

103

Je veux connaître l'enregistrement le plus récent d'une collection. Comment faire ça?

Remarque: je sais que les requêtes de ligne de commande suivantes fonctionnent:

1. db.test.find().sort({"idate":-1}).limit(1).forEach(printjson);
2. db.test.find().skip(db.test.count()-1).forEach(printjson)

où idate a ajouté l'horodatage.

Le problème est que plus la collecte est le temps de récupérer les données et ma collection «test» est vraiment vraiment énorme. J'ai besoin d'une requête avec une réponse en temps constant.

S'il y a une meilleure requête de ligne de commande mongodb, faites-le moi savoir.

inkriti
la source

Réponses:

141

Ceci est une refonte de la réponse précédente, mais il est plus susceptible de fonctionner sur différentes versions de mongodb.

db.collection.find().limit(1).sort({$natural:-1})
Chiffres
la source
12
db.collection.find().limit(1).sort({$natural:-1}).pretty()si vous voulez qu'il soit beau
Anthony
Alors, quelle est la différence avec cette commande:db.collection.find().sort({$natural:-1}).limit(1).pretty()
Leo
@Digits quel impact aura-t-il sur les performances si nous plaçons une limite à la fin, ainsi que la façon dont le dernier enregistrement est récupéré lorsque vous limitez la sortie à un seul document et que ce doit être le premier document de la collection.
kailash yogeshwar
Bonne réponse. J'ai essayé comme ceci: db.collection ("nom de la collection"). Find ({}, {limit: 1}). Sort ({$ natural: -1})
Abdul Alim Shakir
Pour toute personne utilisant AWS DOCDB: Query failed with error code 303 and error message 'option $natural is not supported' on server docdb. Espérons que cette fonctionnalité sera bientôt disponible.
Marc
35

Cela vous donnera un dernier document pour un collection

db.collectionName.findOne({}, {sort:{$natural:-1}})

$natural:-1 signifie l'ordre opposé à celui dans lequel les enregistrements sont insérés.

Edit : Pour tous les downvoters, ci-dessus est une syntaxe Mongoose, la syntaxe mongo CLI est:db.collectionName.find({}).sort({$natural:-1}).limit(1)

dark_ruby
la source
7
Votre syntaxe semble être erronée. Je ne peux pas le faire fonctionner comme vous l'avez. Ce qui fonctionne est: 'db.punchdeck.findOne ({$ query: {}, $ orderby: {$ natural: -1}})'
Dave Lowerre
pas sûr, pourquoi tous les votes négatifs - ce code fonctionne parfaitement pour moi, et est rapide
dark_ruby
2
@dark_ruby Votre requête renvoie l'erreur "$ err": "Impossible de canoniser la requête: BadValue Option de projection non prise en charge: sort: {$ natural: -1.0}",
Roman Podlinov
20

J'ai besoin d'une requête avec une réponse en temps constant

Par défaut, les index de MongoDB sont des B-Trees. La recherche d'un arbre B est une opération O (logN), donc même find({_id:...})ne fournira pas de réponses à temps constant, O (1).

Cela dit, vous pouvez également trier par _idsi vous utilisez ObjectIdpour vos identifiants. Voir ici pour plus de détails . Bien sûr, même cela n'est bon que jusqu'à la dernière seconde.

Vous pouvez recourir à «écrire deux fois». Écrivez une fois dans la collection principale et réécrivez dans une collection "dernière mise à jour". Sans transactions, ce ne sera pas parfait, mais avec un seul article dans la collection «dernière mise à jour», ce sera toujours rapide.

Vice-président Gates
la source
2
Je vois beaucoup de solutions noSQL et MongoDB préconisant «d'écrire deux fois», principalement pour les détenteurs de comptages lorsque la taille des données devient très grande. Je suppose que c'est une pratique courante?
Vinny
MongoDB ne vide pas très souvent le disque et il n'a pas de transactions, donc les écritures deviennent beaucoup plus rapides. Le compromis ici est que vous êtes encouragé à dé-normaliser les données, ce qui conduit souvent à plusieurs écritures. Bien sûr, si vous obtenez un débit d'écriture 10x ou 100x (ce que j'ai vu), alors 2x ou 3x les écritures sont toujours une grande amélioration.
Gates VP
14

Encore une autre façon d'obtenir le dernier élément d'une collection MongoDB (ne vous inquiétez pas des exemples):

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

Projection normale

> db.Sports.find()
{ "_id" : ObjectId("5bfb5f82dea65504b456ab12"), "Type" : "NFL", "Head" : "Patriots Won SuperBowl 2017", "Body" : "Again, the Pats won the Super Bowl." }
{ "_id" : ObjectId("5bfb6011dea65504b456ab13"), "Type" : "World Cup 2018", "Head" : "Brazil Qualified for Round of 16", "Body" : "The Brazilians are happy today, due to the qualification of the Brazilian Team for the Round of 16 for the World Cup 2018." }
{ "_id" : ObjectId("5bfb60b1dea65504b456ab14"), "Type" : "F1", "Head" : "Ferrari Lost Championship", "Body" : "By two positions, Ferrari loses the F1 Championship, leaving the Italians in tears." }

Projection triée (_id: ordre inverse)

> db.Sports.find().sort({'_id':-1})
{ "_id" : ObjectId("5bfb60b1dea65504b456ab14"), "Type" : "F1", "Head" : "Ferrari Lost Championship", "Body" : "By two positions, Ferrari loses the F1 Championship, leaving the Italians in tears." }
{ "_id" : ObjectId("5bfb6011dea65504b456ab13"), "Type" : "World Cup 2018", "Head" : "Brazil Qualified for Round of 16", "Body" : "The Brazilians are happy today, due to the qualification of the Brazilian Team for the Round of 16 for the World Cup 2018." }
{ "_id" : ObjectId("5bfb5f82dea65504b456ab12"), "Type" : "NFL", "Head" : "Patriots Won SuperBowl 2018", "Body" : "Again, the Pats won the Super Bowl" }

sort({'_id':-1}), définit une projection dans l'ordre décroissant de tous les documents, en fonction de leur _ids.

Projection triée (_id: ordre inverse): obtention du dernier (dernier) document d'une collection.

> db.Sports.find().sort({'_id':-1}).limit(1)
{ "_id" : ObjectId("5bfb60b1dea65504b456ab14"), "Type" : "F1", "Head" : "Ferrari Lost Championship", "Body" : "By two positions, Ferrari loses the F1 Championship, leaving the Italians in tears." }
Ivanleoncz
la source
2

php7.1 mongoDB:
$data = $collection->findOne([],['sort' => ['_id' => -1],'projection' => ['_id' => 1]]);

Sam
la source
1

Ma solution:

db.collection("name of collection").find({}, {limit: 1}).sort({$natural: -1})

Abdul Alim Shakir
la source
1

Voici comment obtenir le dernier enregistrement de tous les documents MongoDB de la collection "foo" (changez foo, x, y .. etc.)

db.foo.aggregate([{$sort:{ x : 1, date : 1 } },{$group: { _id: "$x" ,y: {$last:"$y"},yz: {$last:"$yz"},date: { $last : "$date" }}} ],{   allowDiskUse:true  })

vous pouvez ajouter ou supprimer du groupe

articles d'aide: https://docs.mongodb.com/manual/reference/operator/aggregation/group/#pipe._S_group

https://docs.mongodb.com/manual/reference/operator/aggregation/last/

ssymbiotik
la source
0

Si vous utilisez des identifiants d'objets Mongo générés automatiquement dans votre document, il contient un horodatage sous forme de 4 premiers octets en utilisant le dernier document inséré dans la collection. Je comprends que c'est une vieille question, mais si quelqu'un finit toujours ici à la recherche d'une autre alternative.

db.collectionName.aggregate(
[{$group: {_id: null, latestDocId: { $max: "$_id"}}}, {$project: {_id: 0, latestDocId: 1}}])

La requête ci-dessus donnerait le _id du dernier document inséré dans la collection

Chan15
la source