When you create an index for a column, the values ββin the column are literally used as index keys. In your case, the keys for your bitrates index will be objects in the bitrates array in the document.
It seems that you want - this is the index obtained from the values ββin the document field. To do this, you want to define a custom indexing function that reduces the document only to data that interests you. The easiest way to experiment with them is to start by writing a query, and as soon as you are happy with the results, converting it into an indexCreate() statement.
Here is an instruction that captures your sample document (with identifier 1) and discards the terms format and rate from all objects in the bitrate array, and then combines them together to create a separate set of lines:
r.db('music').table('catalog').get(1).do(function(row) { return row('bitrates').map(function(bitrate) { return [bitrate('format'), bitrate('rate')]; }).reduce(function(left, right) { return left.setUnion(right); }) })
Running this statement returns the following:
["mp3", "128K", "aac", "192K"]
It looks good, so we can use our function to create an index. In this case, since we expect the indexing function to return a set of elements, we also want to specify {multi: true} so that we can query the elements in the set, not the set itself:
r.db('music').table('catalog').indexCreate('bitrates', function(row) { return row('bitrates').map(function(bitrate) { return [bitrate('format'), bitrate('rate')]; }).reduce(function(left, right) { return left.setUnion(right); }) }, {multi: true})
After creating, you can query your index as follows:
r.db('music').table('catalog').getAll('mp3', {index: 'bitrates'})
You can also provide several query terms to match strings that match any of the elements:
r.db('music').table('catalog').getAll('mp3', '128K', {index: 'bitrates'})
However, if one document matches more than one term in your request, it will be returned more than once. To fix this, add distinct() :
r.db('music').table('catalog').getAll('mp3', '128K', {index: 'bitrates'}).distinct()
If necessary, you can also use downcase() to normalize the shell of terms used in the secondary index.
You can also completely skip the entire indexing business and use the filter() query:
r.db('music').table('catalog').filter(function(row) { return row('bitrates').map(function(bitrates) { return [bitrates('format'), bitrates('rate')]; }).reduce(function(left, right) { return left.setUnion(right); }).contains('mp3'); })
However, if you almost always query your table in the same way, creating a secondary index using a custom function will result in significantly better performance.