2

我是 mongo db 的新手,所以如果这相当琐碎,请原谅。我非常感谢您的帮助。

这个想法是在某些特定值上生成直方图。在这种情况下,某些文件的 mime 类型。为此,我正在使用地图缩减作业。

我有一个文件格式如下的mongo:

{
    "_id" : ObjectId("4fc5ed3e67960de6794dd21c"),
    "name" : "some name",
    "uid" : "some app specific uid",
    "collection" : "some name",
    "metadata" : [
        {
            "key" : "key1",
            "value" : "Plain text",
            "status" : "SINGLE_RESULT",
        },
        {
            "key" : "key2",
            "value" : "text/plain",
            "status" : "SINGLE_RESULT",
        },
        {
            "key" : "key3",
            "value" : 3469,
            "status" : "OK",
        }
     ]
}

请注意,几乎每个文档中都有更多元数据键值。

地图缩减作业

我尝试执行以下操作:

function map() {
   var mime = "";
   this.metadata.forEach(function (m) {
     if (m.key === "key2") {
        mime = m.value;}
     });
     emit(mime, {count:1});
}

function reduce() {
  var res = {count:0};
  values.forEach(function (v) {res.count += v.count;});
  return res;
}

db.collection.mapReduce(map, reduce, {out: { inline : 1}})

这似乎适用于少量文档(~15K),但问题是在映射阶段遍历所有元数据键值需要大量时间。在更多文档(〜1Mio)上运行此操作时,该操作将永远存在。

所以我的问题是:有什么方法可以直接发出 mime 类型(值),而不是遍历所有键并选择它?或者有没有更好的方法来编写 map reduce 函数。

像 emit (this.metadata.value {$where this.metadata.key:"key2"}) 或类似的东西......

谢谢你的帮助!

4

1 回答 1

6

两个想法...

第一个想法:您对这个文档模式的依附程度如何?您能否将元数据字段值作为嵌入文档而不是嵌入数组,如下所示:

{
    "_id" : ObjectId("4fc5ed3e67960de6794dd21c"),
    "name" : "some name",
    "uid" : "some app specific uid",
    "collection" : "some name",
    "metadata" : {
        "key1" : {
            "value" : "Plain text",
            "status" : "SINGLE_RESULT"
        },
        "key2": {
            "value" : "text/plain",
            "status" : "SINGLE_RESULT"
        }, 
        "key3" : {
            "value" : 3469,
            "status" : "OK"
        }
     }
}

然后您的地图步骤完全取消了循环:

function map() {
   emit( this.metadata["key2"].value, { count : 1 } );
}

那时,您甚至可以将其转换为“组”命令而不是“mapReduce”。

第二个想法:如果没有这样的模式更改,特别是如果“key2”出现在元数据数组的早期,您至少可以在找到密钥后急切地退出循环以节省一些迭代,如下所示:

function map() {
   var mime = "";
   this.metadata.forEach(function (m) {
     if (m.key === "key2") {
        mime = m.value;
        break;
     } 
     });
     emit(mime, {count:1});
}

不确定任何一条道路是否是胜利的关键,但希望有帮助的想法。祝你好运!

于 2012-05-30T17:58:44.433 回答