[ACCEPTED]-Finding The Next Document in MongoDb-mongodb

Accepted answer
Score: 23

It is best to add explicit sort() criteria if 12 you want a predictable order of results.

Assuming 11 the order you are after is "insertion 10 order" and you are using MongoDB's 9 default generated ObjectIds, then you can 8 query based on the ObjectId:

// Find next product created
db.products.find({_id: {$gt: ObjectId("4fdbaf608b446b0477000142") }}).limit(1)

Note that this 7 example only works because:

  • the first four bytes of the ObjectId are calculated from a unix-style timestamp (see: ObjectId Specification)
  • a query on _id alone will use the default _id index (sorted by id) to find a match

So really, this 6 implicit sort is the same as:

db.products.find({_id: {$gt: ObjectId("4fdbaf608b446b0477000142" )}}).sort({_id:1}).limit(1);

If you added 5 more criteria to the query to qualify how 4 to find the "next" product (for 3 example, a category), the query could use a different 2 index and the order may not be as you expect.

You 1 can check index usage with explain().

Score: 0

You can get the items back in insertion 4 order using ObjectId. See: http://www.mongodb.org/display/DOCS/Optimizing+Object+IDs#OptimizingObjectIDs

If you want 3 to get them back in some other order then 2 you will have to define what that order 1 is and store more information in your documents.

Score: 0

Starting in Mongo 5, it's a perfect use case for 1 the new $setWindowFields aggregation operator:

// { _id: 1, name: "product 1" }
// { _id: 2, name: "product 2" }
// { _id: 3, name: "product 3" }
db.collection.aggregate([
  { $setWindowFields: {
    sortBy: { _id: 1 },
    output: { next: { $push: "$$ROOT", window: { documents: [1, 1] } } }
  }}
])
// { _id: 1, name: "product 1", next: [{ _id: 2, name: "product 2" }] }
// { _id: 2, name: "product 2", next: [{ _id: 3, name: "product 3" }] }
// { _id: 3, name: "product 3", next: [ ] }

This:

  • $sorts documents by their order of insertion using their _ids (ObjectIds contain the timestamp of insertion): sortBy: { _id: 1 }
  • adds the next field in each document (output: { running: { ... }})
    • by $pushing the whole document $$ROOT ($push: "$$ROOT")
    • on a specified span of documents (the window) which is in this case is a range of only the next document document: window: { documents: [1, 1] }.

More Related questions