1

我的情况有点奇怪……我有一个故意包含重复项的键列表。为了参数的缘故,我们假设这个列表看起来像[1,2,3,2,1]。目前,获取属于这些 Id 的文档的代码在键列表上循环,调用findOne()并将文档推送到数组中。

所以我们有一个这样的结构:

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

我想知道是否有办法以更……优雅……的方式做到这一点,最好用一个查询?保持订单将是一个加号,但不是严格要求。

编辑: 请注意,这是一个 MongoDB 问题。我正在寻找一种方法来用对 db.items.find() 的一次调用来替换上述循环。

4

2 回答 2

2

我认为没有直接的方法来检索重复键的列表,但是既然你说键是唯一的,你可以使用$in和一些循环来做到这一点:

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]);
}

请注意,虽然它比原来的要长,但它只查询数据库一次。作为奖励,它以与给定键相同的顺序返回文档。

于 2012-08-17T09:09:27.687 回答
0

在 java-script 中使用 for-each 函数应该对您有所帮助:

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

或者我可能错过了你的问题意图完成?但是再次重复的键在任何数组中都不存在..

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]);}
}

这将忽略任何重复项并将它们计为一个,或者您可以对键运行查询,将它们呈现到一个不包含重复项的新数组中

于 2012-08-16T13:13:51.800 回答