我处于一种感觉有点奇怪的情况......我有一个故意包含重复项的密钥列表。为了参数,我们假设这个列表看起来像[1,2,3,2,1]
。目前,获取属于这些Ids的文档的代码循环遍历键列表,调用findOne()
并将文档推送到数组中。
所以我们有这样的结构:
for (var i = 0; i < keys.length; i++) {
documents.push(db.items.findOne(keys[i]);
}
我想知道是否有办法以更优雅......的方式做到这一点,最好只用一个查询?保持订单是一个加号,但并非严格要求。
修改 请注意,这是一个MongoDB问题。我正在寻找一种方法来替换上面的循环,只需调用db.items.find()。
答案 0 :(得分: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]);
}
请注意,虽然它比原始文件长,但它只查询数据库一次。作为奖励,它以与给定键相同的顺序返回文档。
答案 1 :(得分: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]);}
}
将忽略任何重复项并将它们视为一个重复项,或者您可以在键上运行查询,将它们呈现为不包含重复项的新数组