Reputation: 85
I'm trying to work with Rethinkdb in mapreducing something like:
[{"a":1, "b":2}, {"a":3}, {"c":4}]
to {"a":[1,3], "b":[2], "c":[4]}
.
I have already consulted Javascript: How convert array of objects to object with sorted unique arrays? but the statements doesn't really work in ReQL, here's an example:
r.expr([{"a":1, "b":2}, {"a":3}, {"c":4}]).do(function(user){
var c1 = {};
var keys = ["a", "b", "c"];
user.map(function(itm){
keys.map(function(p){
if(!c1[p]){
c1[p] = [];
};
c1[p] = r.expr(c1[p]).setInsert(itm(p).default("NIL"));
});
return 1
});
return c1
});
but this faults out on itm(p) with the error: RqlCompileError: Variable name not found in:
RqlCompileError: Variable name not found in:
r([{a: 1, b: 2}, {a: 3}, {c: 4}]).do(function(var_136) { return {a: r([]).setInsert(var_137("a").default("NIL")), b: r([]).setInsert(var_137("b").default("NIL")), c: r([]).setInsert(var_137("c").default("NIL"))}; })
^^^^^^^
because rethinkdb is assigning variable id (137 in this case) to the itm(p) that's not declared beforehand.
Any ideas how i can do this?
Thanks
Upvotes: 1
Views: 813
Reputation: 2814
Adapting an answer from danielmewes on github
var input = r.expr([{"a":1}, {"a":3}, {b: 2}, {"a":4}, {b: 3}]);
var keys = input.map(function(x){return x.keys()})
.reduce(function(l, r){return l.setUnion(r)});
.map(function(key){ return [key, input(key)]})
.coerceTo('object');
Since this uses some advanced ReQL techniques, here's how it breaks down:
()
in reql is more powerful than regular javascript []
brackets. It will collect the values of the field with that key.[['a', [1,2]], ['b', [3,4]]
[['a', 1], ['b', 2]]
into the object {a: 1, b: 2}
, which is really useful here.Upvotes: 3
Reputation: 85
Here's the answer (or one way to do it), if anyone's wondering...
r.expr([{"a":1, "b":2}, {"a":3}, {"c":4}]).do( r.js("(function(input){
var keys=['a','b','c'], output={};
input.forEach(function(e){
for(var p in e){
output[p] = (output[p] || []).concat(e[p]);
} });
return output; })"
))
Upvotes: 0