scull7
scull7

Reputation: 105

Rethinkdb convert an array of objects to a single object

How would one convert the following:

[{
  "name": "annoying data",
  "status": "evil",
  "frustration": [
   {
      "name": "foo",
      "value": 1
    },
    {
      "name": "bar",
      "value": 2
    },
    {
      "name": "baz",
      "value": 3
    }
  ]
}...]

To this output:

[{
  "name": "annoying data",
  "status": "evil",
  "foo": 1,
  "bar": 2,
  "baz": 3
}...]

from within a rethink query?

We have a stored third-party API response that I am attempting to transform into something useful. In my mind there are 2 things I need to accomplish to reach my end goal of sane data output.

  1. transform the frustration array into an object using name as the keys and value as the values.
  2. merge the newly transformed frustration object into the parent object.

I have a possible solution for step 2:

.map(function(row) {
    row.pluck('name', 'status').merge(row('frustration'))
})

But I'm getting nowhere with step one. Any ideas are much appreciated!

Current full query (names changed to protect... me!):

r.db('test').table('evil_things').map(function(row) {
  var x = row('a')('tree')('children')
        .nth(0)('children')
        .nth(0)
        .map(function(x) {
          return x('children');
        })
        .concatMap(function(x) {
          return x.pluck('name', 'value');
        })
  ;

  return {
    'name': row('name'),
    'status': row('status'),
    'frustration': x
  };
}).filter(function(row) {
  return r.expr(['FOO','BAR','BAZ']).contains(row('name').upcase());
})
.orderBy('status');

Upvotes: 4

Views: 1217

Answers (2)

mlucy
mlucy

Reputation: 5289

Something like this should work:

.map(function(row) {
  return row.pluck('name', 'status').merge(
    row('frustration').map(function(x){ return [x['name'], x['value']]; }).coerceTo('object'))
})

Upvotes: 2

kureikain
kureikain

Reputation: 2314

You are in correct way.

You can create an objects from a key-value list of data with object. But object receive a list of parameters, instead of an array so you need args.

frustation is an array with each document as object, you need a way to turn it into a list of flatten array, meaning from this array

[{key1: val1}, {key2: val2},...]

we turn it to

[key1, val1, key2, val2,...]

to feed into args for object. That's the job of concatMap.

Let's try this:

r.expr([{
  "name": "annoying data",
  "status": "evil",
  "frustration": [
    {
      "name": "foo",
      "value": 1
    },
    {
      "name": "bar",
      "value": 2
    },
    {
      "name": "baz",
      "value": 3
    }
  ]
}])
.map(function(doc) {
  return doc.pluck("name", "status").merge(
    r.object(r.args(doc('frustration')
     .concatMap(function(frustration) { return [frustration("name"), frustration("value")] })
    ))
  )
})

Result:

[
{
"bar": 2 ,
"baz": 3 ,
"foo": 1 ,
"name":  "annoying data" ,
"status":  "evil"
}
]

Hope it helps:

Upvotes: 3

Related Questions