Saint
Saint

Reputation: 5469

Get position of selected document in collection [mongoDB]

How to get position (index) of selected document in mongo collection?

E.g. this document: db.myCollection.find({"id":12345}) has index 3 in myCollection

myCollection:
    id: 12340, name: 'G'
    id: 12343, name: 'V'
    id: 12345, name: 'A'
    id: 12348, name: 'N'

Upvotes: 29

Views: 24306

Answers (6)

user2584621
user2584621

Reputation: 2723

The queries I use that return the entire collection all use sort to get a reproducible order, find.sort.forEach works with the script above to get the correct index.

Upvotes: 0

Nuelsian
Nuelsian

Reputation: 521

Restructure your collection to include the position of any entry i.e {'id': 12340, 'name': 'G', 'position': 1} then when searching the database collection(myCollection) using the desired position as a query

Upvotes: 0

lingeshram
lingeshram

Reputation: 651

This might be very slow but straightforward method. Here you can pass as usual query. Just I am looping all the documents and checking if condition to match the record. Here I am checking with _id field. You can use any other single field or multiple fields to check it.

var docIndex = 0;
db.url_list.find({},{"_id":1}).forEach(function(doc){
  docIndex++;
  if("5801ed58a8242ba30e8b46fa"==doc["_id"]){
    print('document position is...' + docIndex);
    return false;
  }
});

Upvotes: 3

DhruvPathak
DhruvPathak

Reputation: 43245

If your requirement is to find the position of the document irrespective of any order, that is not possible as MongoDb does not store the documents in specific order. However,if you want to know the index based on some field, say _id , you can use this method.

If you are strictly following auto increments in your _id field. You can count all the documents that have value less than that _id, say n , then n + 1 would be index of the document based on _id.

n = db.myCollection.find({"id": { "$lt" : 12345}}).count() ;

This would also be valid if documents are deleted from the collection.

Upvotes: 45

jhonkola
jhonkola

Reputation: 3435

As far as I know, there is no single command to do this, and this is impossible in general case (see Derick's answer). However, using count() for a query done on an ordered id value field seems to work. Warning: this assumes that there is a reliably ordered field, which is difficult to achieve in a concurrent writer case. In this example _id is used, however this will only work with a single writer case.:

MongoDB shell version: 2.0.1
connecting to: test
> use so_test
switched to db so_test
> db.example.insert({name: 'A'})
> db.example.insert({name: 'B'})
> db.example.insert({name: 'C'})
> db.example.insert({name: 'D'})
> db.example.insert({name: 'E'})
> db.example.insert({name: 'F'})
> db.example.find()
{ "_id" : ObjectId("4fc5f040fb359c680edf1a7b"), "name" : "A" }
{ "_id" : ObjectId("4fc5f046fb359c680edf1a7c"), "name" : "B" }
{ "_id" : ObjectId("4fc5f04afb359c680edf1a7d"), "name" : "C" }
{ "_id" : ObjectId("4fc5f04dfb359c680edf1a7e"), "name" : "D" }
{ "_id" : ObjectId("4fc5f050fb359c680edf1a7f"), "name" : "E" }
{ "_id" : ObjectId("4fc5f053fb359c680edf1a80"), "name" : "F" }
> db.example.find({_id: ObjectId("4fc5f050fb359c680edf1a7f")})
{ "_id" : ObjectId("4fc5f050fb359c680edf1a7f"), "name" : "E" }
> db.example.find({_id: {$lte: ObjectId("4fc5f050fb359c680edf1a7f")}}).count()
5
> 

This should also be fairly fast if the queried field is indexed. The example is in mongo shell, but count() should be available in all driver libs as well.

Upvotes: 4

Derick
Derick

Reputation: 36784

There is no way that MongoDB can return this as it does not keep documents in order in the database, just like MySQL f.e. doesn't name row numbers.

The ObjectID trick from jhonkola will only work if only one client creates new elements, as the ObjectIDs are generated on the client side, with the first part being a timestamp. There is no guaranteed order if different clients talk to the same server. Still, I would not rely on this.

I also don't quite understand what you are trying to do though, so perhaps mention that in your question? I can then update the answer.

Upvotes: 1

Related Questions