7

I'm in the learning phase of mongodb.

I have a test website project where each step of a story is a domain.com/step for instance, step 14 is accessed through domain.com/14

In other words, for the above case, I will need to access 14th document in my collection to serve it.

I've been using find().skip(n).limit(1) method for this so far to return nth document however it becomes extremely slow when there are too many documents to skip. So I need a more efficient way to get the nth document in my collection.

Any ideas are appreciated.

Mia
  • 6,220
  • 12
  • 47
  • 81
  • Ranged pagination is normally the case, a few samples from Google http://stackoverflow.com/questions/7228169/slow-pagination-over-tons-of-records-in-mongo http://stackoverflow.com/questions/9703319/mongodb-ranged-pagination http://blog.mongodirector.com/fast-paging-with-mongodb/ – Sammaye Aug 08 '15 at 18:42
  • @Sammaye thank you for the links, however I've seen them and they're not the answer of my question. I'm not looking for a pagination, I'm needing to access to direct domain.com/step links - second and the third links you've given are completely about pagination with skip, and the first link does not have an answer but a suggestion: "do not use it" All of those are actually the reasons of my question being here. – Mia Aug 08 '15 at 18:45
  • Really **good** example of forward paging. And also a duplicate of: http://stackoverflow.com/questions/31675598/how-to-efficiently-page-batches-of-results-with-mongodb/31676400#31676400 – Blakes Seven Aug 08 '15 at 18:46
  • But you are getting the 14th document in a sort, hence you use skip(), what would stop you from using a piece of information to $gt or $min all documents before and then use limit one to get that 14th document? – Sammaye Aug 08 '15 at 18:49
  • **Excellent** example of forawrd paging and another duplicate: http://stackoverflow.com/questions/28105009/implementing-pagination-in-mongodb – Blakes Seven Aug 08 '15 at 18:51
  • @Sammaye can you exemplify please - I'm just learning mongodb, can't process what you said entirely – Mia Aug 08 '15 at 18:51
  • Wait, question: do you know anything about the documents, except their position when you look for them? – Sammaye Aug 08 '15 at 18:52
  • Like, do you know the _id of the previous document in the line? – Sammaye Aug 08 '15 at 18:53
  • Well I'd rather use the auto-incremental field of your other question but not skip! The autoincremental way may need two requests per insert but at least the "R, U, D" operations of CRUD work great. Cf http://stackoverflow.com/questions/31897019/incremental-field-to-existing-collection – dotpush Aug 08 '15 at 18:54
  • @Sammaye no -- I just add them in order, and expect them to stay in the same order in _id. At the moment I'm using .toArray in javascript to create an array of all existing documents in memory and get nth indexed item from the array, which returns my document. But this is of course very costy memory-wise – Mia Aug 08 '15 at 18:54
  • @Sammaye my documents are pretty simple. What Ipush in is {text:"text":date:date,imageurl:"imageurl"} - what do you mean "an AI might be better" – Mia Aug 08 '15 at 18:56
  • @dotpush that was the reason of me creating that auto increment thread. At least direct access to documents via index – Mia Aug 08 '15 at 18:57
  • So by AI I mean Auto incrementing ID, sorry it is the term commonly used in MySQL. The problem is that even though your documents are really simple you need something to latch onto so you can range and avoid the nasty skip – Sammaye Aug 08 '15 at 19:14
  • Since you cannot do that with the last document ID or otherwise you probably could do with adding a AI – Sammaye Aug 08 '15 at 19:14
  • @Sammaye I see - I was hoping for an internal method to make queries with the order index – Mia Aug 08 '15 at 19:15
  • Unfortunately not, skip is the best thing at that. It actually travels the btree index to that position, that's why it is so slow on higher values – Sammaye Aug 08 '15 at 19:34

1 Answers1

5

Add a field to your documents which tells you which step it is, add an index to that field and query by it.

Document:

{
     step:14
     text:"text",
     date:date,
     imageurl:"imageurl"
}

Index:

db.collection.createIndex({step:1});

Query:

db.collection.find({step:14});

Relying on natural order in the collection is not just slow (as you found out), it is also unreliable. When you start a new collection and insert a bunch of documents, you will usually find them in the order you inserted them. But when you change documents after they were inserted, it can happen that the order gets messed up in unpredictable ways. So never rely on insertion order being consistent.

Exception: Capped Collections guarantee that insertion order stays consistent. But there are very few use-cases where these are useful, and I don't think you have such a case here.

Philipp
  • 67,764
  • 9
  • 118
  • 153