1

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

3
  • You seem to be using an array ['a','b','c'] to specify the order of the keys in the returned object, but javascript Objects do not have an order, the keys may be returned in any sequence regardless of the order they were added (or alphabetic or numeric order). In practice, most browsers will return object properties in the order they were added, but that is not guaranteed and is inconsistent in some browsers in some cases and can't be relied on. Commented Mar 21, 2015 at 0:03
  • @RobG Thanks. I don't think I'm particular about the order, just the mechanism of converting [{}] to {[]}. I distilled the code a bit more and found what looks like a bug in ReQL and I've filed a issue here Commented Mar 21, 2015 at 0:12
  • Cool, just so you know… :-) Commented Mar 21, 2015 at 6:42

2 Answers 2

3

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:

  1. First we grab the keys of every object in the array. This results in an array of arrays
  2. Next we reduce, this does a pairwise combination of elements from the previous array of arrays. What we end up with is a deduplicated list of all keys in any of the objects in the original array.
  3. Next, for each key, we create a two element array where the first element is the key, and the second element is an array of all of the values in the original input with that key.
    • this works because () in reql is more powerful than regular javascript [] brackets. It will collect the values of the field with that key.
    • the output of this step is an array of arrays like [['a', [1,2]], ['b', [3,4]]
  4. Finally, we coerce to an object. ReQL can coerce arrays like [['a', 1], ['b', 2]] into the object {a: 1, b: 2}, which is really useful here.
Sign up to request clarification or add additional context in comments.

Comments

0

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; })"
))

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.