当您为列创建索引时,列中的值按字面意思用作索引的键。在您的情况下,您的 bitrates 索引的键将是文档中 bitrates 数组中的对象。
您想要的似乎是从文档字段中的值派生的索引。为此,您需要定义一个自定义索引函数,将文档缩减为您关心的数据。试验它们的最简单方法是先编写一个查询,一旦您对结果感到满意,就将其转换为 indexCreate() 语句。
这是一个语句,它获取您的示例文档(id 为 1),并从其 bitrate 数组中的所有对象中提取 format 和 rate 术语,然后将它们合并在一起以创建一个不同的集合字符串:
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);
})
})
运行此语句将返回以下内容:
["mp3", "128K", "aac", "192K"]
这看起来不错,所以我们可以使用我们的函数来创建索引。在这种情况下,由于我们期望索引函数返回一组项目,我们还希望指定 {multi: true} 以确保我们可以通过集合中的 items 而不是集合本身进行查询:
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})
创建后,您可以像这样查询索引:
r.db('music').table('catalog').getAll('mp3', {index: 'bitrates'})
您还可以提供多个查询词,以匹配与任何项目匹配的行:
r.db('music').table('catalog').getAll('mp3', '128K', {index: 'bitrates'})
但是,如果单个文档与您的查询中的多个词匹配,它将被多次返回。要解决此问题,请添加 distinct():
r.db('music').table('catalog').getAll('mp3', '128K', {index: 'bitrates'}).distinct()
如有必要,您还可以考虑使用downcase() 来规范二级索引中使用的术语的大小写。
您也可以完全跳过所有索引业务并使用filter() 查询:
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');
})
也就是说,如果您几乎总是以相同的方式查询表,那么使用自定义函数生成二级索引会显着提高性能。