【问题标题】:Map/Reduce on an array of hashes in CouchDB在 CouchDB 中的哈希数组上映射/减少
【发布时间】:2010-03-16 12:29:37
【问题描述】:

我正在寻找一个 map/reduce 函数来计算设计文档中的状态。 您可以在下面看到我当前数据库中的示例文档。

{
   "_id": "0238f1414f2f95a47266ca43709a6591",
   "_rev": "22-24a741981b4de71f33cc70c7e5744442",
   "status": "retrieved image urls",
   "term": "Lucas Winter",
   "urls": [
       {
           "status": "retrieved",
            "url": "http://...."
       },
       {
           "status": "retrieved",
            "url": "http://..."
       }
   ],
   "search_depth": 1,
   "possible_labels": {
       "gender": "male"
    },
    "couchrest-type": "SearchTerm"
}

我想去掉 status 键,而是从 url 的状态中计算它。 我当前的by_status 视图如下所示:

function(doc) {
    if (doc['status']) {
       emit(doc['status'], null);
    }
}

我尝试了一些东西,但实际上没有任何效果。现在我的Map Function 看起来像这样:

function(doc) {
    if(doc.urls){
        emit(doc._id, doc.urls)
    }
}

还有我的Reduce Function

function(key, value, rereduce){ 
    var reduced_status = "retrieved"
    for(var url in value){
        if(url.status=="new"){
            reduced_status = "new";
        }
    }
    return reduced_status;
}

结果是我到处都被检索到,这绝对是不对的。

我试图缩小问题范围,似乎value 不是数组,当我使用以下Reduce Function 时,我到处都得到长度 1,这是不可能的,因为我的数据库中有 12 个文档,每个包含 20 到 200 个网址

function(key, value, rereduce){ 
   return value.length;
}

alt text http://img.skitch.com/20100316-qeawxgd5pru8d5i6bprygcsmhf.jpg

我做错了什么? (我知道我想让你为我写代码,我很内疚,但现在我在从数据库中获取数据后,在 ruby​​ 中计算状态。如果已经从数据库中获取了正确的数据,那就太好了数据库)

【问题讨论】:

  • JSON.stringify(value) 返回什么? (JSON 是 Firefox 3.5+ 中的原生窗口对象)

标签: javascript couchdb mapreduce


【解决方案1】:

reduce 函数的变量value 是一个由map 函数发出的值数组。在您的情况下,value 是一个由“url”数组组成的数组。在蒲团中运行 map-reduce 时,它​​设置 group=true 以便为 map 函数发出的每个键单独运行 map-reduce。在您的情况下,这些键是文档_ids。即reduce函数的value是一个数组,其元素都是属于某个doc_id的url数组。由于 doc _ids 是唯一的,因此您最终会得到 reduce 函数的 value 是一个包含一个元素的数组,该元素是相应 doc 的 url-array。这就是为什么 value.length 在您的 reduce 函数中始终为 1 的原因。

但情况可能会变得更糟:如果您最终进入一个 rereduce 循环,reduce 函数的 value 是一个值数组,由之前对 reduce 函数的调用返回。在您的情况下,您会使用看起来像 ["retrieved","new","retrieved"]value 调用 reduce 函数,这不会导致正确的结果。

通常,reduce 函数用于聚合 map 函数发出的数据,例如计算行数或汇总值 - 这在您的情况下不是必需的。您可以在此处阅读有关 couchdb 中的 map-reduce 的更多信息:

http://wiki.apache.org/couchdb/Introduction_to_CouchDB_views

http://books.couchdb.org/relax/design-documents/views

【讨论】:

    【解决方案2】:

    doc.urls 似乎是一个 Objects 数组,其中包含一个 status 属性和一个 url 属性。所以你的 Reduce 函数应该是这样的

    function(key, value, rereduce){ 
        var reduced_status = "retrieved";
        for(var i=0; i<value.length; i++) {
            if(value[i].status=="new"){
                reduced_status = "new";
            }
        }
        return reduced_status;
    }
    

    编辑:实际上该函数应在找到status == "new" 后立即返回。

    【讨论】:

    • 唯一的问题是,value.length 始终为 1 - 请参阅我原始问题的下三分之一 - 我不知道为什么,因为 doc.urls 应该包含 20 到 200 个哈希值。
    • 好的,但是您的 Reduce 函数仍然非常错误。 For..in 不像你认为的那样工作。
    【解决方案3】:

    感谢 Alsciende 将我推向正确的解决方案,结果我真的不了解 reduce 功能。我根本不需要reduce函数。

    这是我的Map Function,它为我解决了这个问题。

    function(doc) {
    if(doc.urls){
      var reduced_status = "retrieved";
      for(var i=0; i<doc.urls.length; i++) {
        if(doc.urls[i].status=="new"){
            reduced_status = "new";
            break;
        }
      }
      emit(reduced_status, null);
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2012-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-11
      • 2018-08-05
      • 1970-01-01
      • 2021-06-11
      • 1970-01-01
      相关资源
      最近更新 更多