cloudant - make couchDB calculate an average and keep it up to date when adding values -
is possible make couchdb (cloudant) calculate average rating
value of each document ? if yes, how in cloudant ?
thanks.
{ "_id": "2016-02-06t13:16:30.515z", "_rev": "3-7521b9e21fbb58d5393a76d08b12ab12", "modelstrict": "taj model", "ratings": { "2016-02-06t13:36:04.671z": { "useremail": "lourain@yaho.fr", "rating": 1, "sessionnumber": 0 }, "2016-02-06t13:46:04.671z": { "useremail": "louin@yaoo.fr", "rating": 3, "sessionnumber": 0 }, "2016-02-06t13:53:04.671z": { "useremail": "luin@yaoo.fr", "rating": 3, "sessionnumber": 0 }, "2016-02-06t13:47:04.671z": { "useremail": "loin@yaoo.fr", "rating": 5, "sessionnumber": 0 } }, "averagerating": ... }
and how keep averagerating to date when rating added ?
an added rating looks this:
"2016-02-06t17:57:04.671z": { "useremail": "loin@yaoo.fr", "rating": 2, "sessionnumber": 10 }
couchdb doesn't computed fields in documents. however, map/reduce perfect doing calculation incrementally, because couchdb efficient it's map/reduce calculations. (you can read more design decisions , impact on performance here)
my recommendation create separate documents each rating:
{ "modelstrict": "taj model", "datetime": "2016-02-06t13:36:04.671z", "useremail": "lourain@yaho.fr", "rating": 1, "sessionnumber": 0 } { "modelstrict": "taj model", "datetime": "2016-02-06t13:46:04.671z", "useremail": "louin@yaoo.fr", "rating": 3, "sessionnumber": 0 } { "modelstrict": "taj model", "datetime": "2016-02-06t13:53:04.671z", "useremail": "luin@yaoo.fr", "rating": 3, "sessionnumber": 0 } { "modelstrict": "taj model", "datetime": "2016-02-06t13:47:04.671z", "useremail": "loin@yaoo.fr", "rating": 5, "sessionnumber": 0 }
then, can use map function this, group ratings modelstrict
(which appears key)
function (doc) { emit(doc.modelstrict, doc.rating); }
then, can use reduce function calculating average: (i modified reduce function here
function(keys, values, rereduce) { if (!rereduce) { var length = values.length return [sum(values) / length, length] } else { var length = sum(values.map(function(v){return v[1]})); var avg = sum(values.map(function(v){ return v[0] * (v[1] / length) })); return [avg, length] } }
when call view, you'll [ 3, 4 ]
, average number of values used compute average. believe need return both both reduce
, rereduce
have enough context make calculation, 1 of weird couchdb-isms.
as use couchdb more , more, you'll find using more documents rather merging lot same document. makes writing views more flexible , more efficient on disk usage, of course experiment works best own application. hope helps!
Comments
Post a Comment