2010-03-16 4 views
2

Я ищу функцию map/reduce, чтобы рассчитать статус в Design Document. Ниже вы можете увидеть пример документа из моей текущей базы данных.Карта/Уменьшить массив хэшей в CouchDB

{ 
    "_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 и достаточно вычислить его из статусов URLs. Мой текущий 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 URLs

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

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

Что я делаю неправильно? (Я знаю, что хочу, чтобы вы писали код для меня, и я чувствую себя виноватым, но сейчас я делаю расчет статусов в рубине после получения данных из базы данных. Было бы неплохо уже получить правильные данные из база данных)

+0

Что JSON.stringify (стоимость) возвращается? (JSON является родным объектом окна в Firefox 3.5+) – Alsciende

ответ

3

Переменная value функции снижения является массивом значений, излучаемый с помощью функции карты. В вашем случае value представляет собой массив, состоящий из «url» -арравов. При запуске map-reduce в futon он устанавливает group=true, так что уменьшение карты выполняется отдельно для каждого ключа, испускаемого функцией карты. В вашем случае эти ключи являются документом _ids. То есть, функция уменьшения функции value представляет собой массив, элементами которого являются все url-массивы, принадлежащие определенному документу _id. Поскольку doc _ids уникальны, в итоге вы получаете функцию value функции reduce, являющуюся массивом с одним элементом, этот элемент является url-массивом соответствующего документа. Вот почему value.length всегда 1 с вашей функцией уменьшения.

Но это может ухудшиться: если вы закончите цикл rereduce, функция value функции уменьшения - это массив значений, возвращаемый предыдущим вызовом функции уменьшения. В вашем случае, вы назвали бы уменьшить функцию с value глядя, как ["retrieved","new","retrieved"], который не приводит к правильным результатам.

Как правило, функция снижения используется для сбора данных, испускаемых карта-функцией, например, для подсчета строк или суммировать значение - который не является необходимым в вашем случае. Вы можете прочитать больше о карте-свертка в CouchDB здесь:

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

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

1

doc.urls представляется массивом Object s, содержащим status и url. Таким образом, ваша функция Снижение должно быть что-то вроде

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".

+0

Единственная проблема в том, что value.length всегда 1 - см нижней трети моего первоначального вопроса - и я не знаю, почему, потому что doc.urls должен содержать от 20 и 200 хешей. – sebastiangeiger

+0

Хорошо, но тем не менее, функция «Уменьшить» очень не правильная. Для .. не работает так, как вы, кажется, думаете, что это работает. – Alsciende

0

Спасибо Alsciende за то, что он подтолкнул меня к правильному решению, оказалось, что я действительно не понял функцию уменьшения. Мне вообще не нужна функция сокращения.

Вот мой 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); 
    } 
} 
Смежные вопросы