Samuel Goldenbaum
Samuel Goldenbaum

Reputation: 18919

RethinkDB: RqlRuntimeError: Cannot perform bracket on a sequence of sequences

Given the following documents in a table:

[
  {
    "id": "d30aa369-99d6-4a40-9547-2cbdf0bb069a",
    "locations": [
      {
        "alerts": [
          {"person": 200},
          {"person": 300}
        ],
        "name": "home"
      },
      {
        "alerts": [
          {"person": 200},
          {"person": 300}
        ],
        "name": "work"
      }
    ],
    "person": 100
  },
  {
    "id": "d671d2c7-0e0d-43c0-9148-9e6b049b49a7",
    "locations": [
      {
        "alerts": [
          {"person": 100},
          {"person": 300}
        ],
        "name": "home"
      },
      {
        "alerts": [
          {"person": 100},
          {"person": 300}
        ],
        "name": "work"
      }
    ],
    "person": 200
  }
] 

I want to return all locations that have an alert containing a particular person. I thought it would go a little something like this:

r.db('db').table('test')('locations').filter(function(location){
  return location('alerts')('person').eq(200);
});

Yet I get:

RqlRuntimeError: Cannot perform bracket on a sequence of sequences in:

What is the correct way to execute this query?

Upvotes: 3

Views: 1280

Answers (1)

deontologician
deontologician

Reputation: 2824

Whenever you get the "sequence of sequences" error, the solution usually involves using concatMap.

In this case, I think this will get you what you want:

r.db('db').table('table')
    .concatMap(r.row('locations'))
    .filter(r.row('alerts')('person').contains(200))

concatMap with the identity function function(x){return x} is also known as "flatten" (though there isn't a reql term called flatten)

Edit:

If you want to return the entire top level document, you need to push the concatMap down a bit further, and use the "flatten" idiom I mentioned above:

r.db('db').table('table').filter(function(person){
    return person
      ('locations')
      ('alerts')
      .concatMap(function(x){return x}) // flatten
      ('person')
      .contains(200)
})

Upvotes: 6

Related Questions