Im trying to do a simple view where it only emits documents where the id begins with "rating-". I dont seem to be able to call any "string:" functions at all in couchdb. Really not sure how to go about this... Every example I've have seen never compares part of value, always the entire value. In ecmascript i'd probably just do if (!doc._id.indexOf('rating-')). In this code below it complains one of the arguments supplied to split is invalid.
fun({Doc}) ->
Id = proplists:get_value(<<"_id">>, Doc),
DocChk = binary:split(Id, <<"-">>),
case array:get(0, DocChk) of
<<"rating-">> -> Emit(Id, nil)
end
end.
I've had a few attempts, i've been trying out things in the Erlang shell and while I can occasionally not get a syntax error I can never get anything to run on couchdb. This the whole view i'm trying to adapt from ecmascript. As you can see... i'm still stuck on line 1 lol.
Map
function (doc) {
if (doc._id.indexOf('rating-') !== 0) return;
if (!doc.isValid) return;
var nps;
doc.results.forEach(function (r) {
if (r.type === 'Nps') {
nps = r;
}
});
if (!nps) return;
var result = { t: 1, d: 0, p: 0 };
switch (nps.score) {
case 10:
case 9:
result.p++;
break;
case 8:
case 7:
break;
default:
result.d++;
break;
}
var week = new Date(doc.dateCaptured.year, doc.dateCaptured.month -1, doc.dateCaptured.day);
week.setDate(week.getDate() - ((week.getDay() === 0 ? 7 : week.getDay())-1));
emit(['week', doc.companyId, week.getFullYear(), week.getMonth()+1, week.getDate()], result);
emit(['day', doc.companyId, doc.dateCaptured.year, doc.dateCaptured.month, doc.dateCaptured.day], result);
emit(['month', doc.companyId, doc.dateCaptured.year, doc.dateCaptured.month], result);
emit(['year', doc.companyId, doc.dateCaptured.year], result);
emit(['week-bylocation', doc.companyId, doc.locationId, week.getFullYear(), week.getMonth()+1, week.getDate()], result);
emit(['day-bylocation', doc.companyId, doc.locationId, doc.dateCaptured.year, doc.dateCaptured.month, doc.dateCaptured.day], result);
emit(['month-bylocation', doc.companyId, doc.locationId, doc.dateCaptured.year, doc.dateCaptured.month], result);
emit(['year-bylocation', doc.companyId, doc.locationId, doc.dateCaptured.year], result);
emit(['week-bysource', doc.companyId, doc.sourceId, week.getFullYear(), week.getMonth()+1, week.getDate()], result);
emit(['day-bysource', doc.companyId, doc.sourceId, doc.dateCaptured.year, doc.dateCaptured.month, doc.dateCaptured.day], result);
emit(['month-bysource', doc.companyId, doc.sourceId, doc.dateCaptured.year, doc.dateCaptured.month], result);
emit(['year-bysource', doc.companyId, doc.sourceId, doc.dateCaptured.year], result);
}
Reduce
function (keys, values, rereduce) {
var result = { t: 0, p: 0, d: 0 };
values.forEach(function (v) {
result.t += v.t;
result.p += v.p;
result.d += v.d;
});
return result;
}
The performance of this view is just too slow. It wouldnt' be a problem incrementally but i have to seed index 6.3M rows and it would take about 12hours on 3 node cluster with a total of 12 cores. Definately cpu bound.
Edit
Thanks to Hynek I've been able to port my map function. I'm sure its very inefficient erlang but it seems to be about 30 times faster than its ecmascript counterpart.
fun({Doc}) ->
case lists:keyfind(<<"_id">>, 1, Doc) of
{_, <<"rating-", _/bytes>> = Id} ->
case couch_util:get_value(<<"isValid">>, Doc) of
true ->
Results = proplists:get_value(<<"results">>, Doc),
case lists:dropwhile(fun({R}) -> <<"Nps">> /= proplists:get_value(<<"type">>, R) end, Results) of
[] -> ok;
[{Nps} | _] ->
Score = proplists:get_value(<<"score">>, Nps),
A = case Score of
S when S > 8 -> [1, 0, 1];
S when S > 6 -> [0, 0, 1];
_ -> [0, 1, 1]
end,
CompanyId = proplists:get_value(<<"companyId">>, Doc),
LocationId = proplists:get_value(<<"locationId">>, Doc),
SourceId = proplists:get_value(<<"sourceId">>, Doc),
{DateCaptured} = proplists:get_value(<<"dateCaptured">>, Doc),
Year = proplists:get_value(<<"year">>, DateCaptured),
Month = proplists:get_value(<<"month">>, DateCaptured),
Day = proplists:get_value(<<"day">>, DateCaptured),
Emit([<<"year">>, CompanyId, Year], A),
Emit([<<"month">>, CompanyId, Year, Month], A),
Emit([<<"day">>, CompanyId, Year, Month, Day], A),
Emit([<<"year-bylocation">>, CompanyId, LocationId, Year], A),
Emit([<<"month-bylocation">>, CompanyId, LocationId, Year, Month], A),
Emit([<<"day-bylocation">>, CompanyId, LocationId, Year, Month, Day], A),
Emit([<<"year-bysource">>, CompanyId, SourceId, Year], A),
Emit([<<"month-bysource">>, CompanyId, SourceId, Year, Month], A),
Emit([<<"day-bysource">>, CompanyId, SourceId, Year, Month, Day], A)
end;
_ -> ok
end;
_ -> ok
end
end.
=/=instead of/=inlists:dropwhile/2anybody would recognize it as code written by very experienced Erlang developer. - Hynek -Pichi- Vychodillists:keysearch/3butproplists:get_value/2is much slower erlang function. - Hynek -Pichi- Vychodil