1

I am in a situation that feels a little odd ... I have a list of keys deliberately containing duplicates. For the sake of the arguments lets assume this list looks like [1,2,3,2,1]. Currently the code to fetch the documents belonging to these Ids loops over the list of keys, calls findOne() and pushes the document into an array.

So we have a construct like this:

for (var i = 0; i < keys.length; i++) {
  documents.push(db.items.findOne(keys[i]);
}

I am wondering whether there is a way to do this in a more ... elegant ... fashion, preferably with a single query? Keeping the order would be a plus but is not strictly required.

Edit: Please note that this is a MongoDB question. I am looking for a way to substitute the above loop with a single call to db.items.find().

Marcus Riemer
  • 7,244
  • 8
  • 51
  • 76

2 Answers2

2

I don't think there's a direct way to retrieve a list for duplicate keys, but since you said that keys are unique you could do it using $in and some looping:

var keys = [1,2,3,2,1];
var docHash = {}; //auxiliary hashtable containing mapping id -> document

var documents = []; //the result

db.items.find({id : {$in : keys}})
     .forEach(
         function(doc) {
             //if multiple documents can have the same key change it to:
             // if (docHash[doc.id]) { 
             //     docHash[doc.id].push(doc);
             // } else {
             //     docHash[doc.id] = [doc];
             // } 
             docHash[doc.id] = doc; 
         });

keys.forEach(function(i) {
     // if multiple documents can have the same key change it to:
     // docHash[i].forEach(function(item) {documents.push(item);});
     documents.push(docHash[i]);
}

Note that, while it's longer than the original, it queries the database only once. As a bonus it returns documents in the same order as the given keys.

soulcheck
  • 36,297
  • 6
  • 91
  • 90
0

use for-each function in java-script that should help you a bit:

for (var i in keys) {// i will be  1 ,2 ,3 ,3 ,1
   documents.push(db.items.findOne(i);      
 }

or i might've missed your questions intention complety? but then again duplicate keys do not exist in any array..

var used=Array();
for (var i = 0; i < keys.length; i++) {
  if (!used[keys[i]]){
       used[keys[i]]=1;
       documents.push(db.items.findOne(keys[i]);}
}

that will ignore any duplicates and count them as one eather that or you can run query on the keys rendering them in to a new array that does not contains duplicates

volchkov
  • 69
  • 7
  • Maybe I should add some emphasis that this is a MongoDB question ... I am looking for a way to optimise the multiple calls of findOne() by using a single find() operation. – Marcus Riemer Aug 16 '12 at 13:20
  • Ok i'm not a big expert but let me get this you have an array of data that gets one of those right? – volchkov Aug 16 '12 at 13:29
  • I am not sure I understand what you mean ... The duplicate keys are there on purpose, I don't want to filter them. – Marcus Riemer Aug 16 '12 at 14:23
  • 1
    Sounds like your schema choice isn't well suited for the use case you have. – Asya Kamsky Aug 17 '12 at 02:34