如何在对象数组中查询RethinkDB中的多索引

7 rethinkdb

我正在使用一个看起来像这样的数据集:

"bitrates": [
  {
    "format":  "mp3" ,
    "rate":  "128K"
  } ,
  {
    "format":  "aac" ,
    "rate":  "192K"
  }
] ,
"details": [ ... ] ,
"id": 1 ,
"name":  "For Those About To Rock We Salute You" ,
"price": 1026 ,
"requires_shipping": false ,
"sku":  "ALBUM-1" 
}
Run Code Online (Sandbox Code Playgroud)

我想在bitratesflexing 上创建一个二级索引{multi:true}.这是我的尝试:

r.db("music").table("catalog").indexCreate("bitrates", {multi: true})
Run Code Online (Sandbox Code Playgroud)

索引构建得很好,但是当我查询它时,没有任何返回 - 这似乎与我在这里读到的每个例子相反:

http://rethinkdb.com/docs/secondary-indexes/javascript/

我写的查询是这样的:

r.db("music").table("catalog").getAll(["mp3", "128K"], {index : "bitrates"})
Run Code Online (Sandbox Code Playgroud)

没有错误,只有0个结果(我有300个左右的文档,包含这些确切的数据).

我正在使用RethinkDB 2.0 RC1.

Nat*_*ari 12

为列创建索引时,列中的值将按字面用作索引的键.在您的情况下,bitrates索引的键将是bitrates文档中数组中的对象.

看起来你想要的是一个从文档字段中的值派生的索引.为此,您需要定义自定义索引功能,将文档简化为您关注的数据.最简单的实验方法是从编写查询开始,一旦您对结果感到满意,就将其转换为indexCreate()语句.

这是一个语句,它抓取您的示例文档(ID为1),并从其数组中的所有对象中获取formatrate术语bitrate,然后将它们合并在一起以创建一组不同的字符串:

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);
  })
})
Run Code Online (Sandbox Code Playgroud)

运行此语句将返回以下内容:

["mp3", "128K", "aac", "192K"]
Run Code Online (Sandbox Code Playgroud)

这看起来很好,所以我们可以使用我们的函数来创建索引.在这种情况下,由于我们期望索引函数返回一组项,我们还要指定{multi: true}以确保我们可以按集中的查询,而不是集本身:

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})
Run Code Online (Sandbox Code Playgroud)

创建后,您可以像这样查询索引:

r.db('music').table('catalog').getAll('mp3', {index: 'bitrates'})
Run Code Online (Sandbox Code Playgroud)

您还可以提供多个查询字词,以匹配与任何项匹配的行:

r.db('music').table('catalog').getAll('mp3', '128K', {index: 'bitrates'})
Run Code Online (Sandbox Code Playgroud)

但是,如果单个文档与查询中的多个术语匹配,则会多次返回该文档.要解决此问题,请添加distinct():

r.db('music').table('catalog').getAll('mp3', '128K', {index: 'bitrates'}).distinct()
Run Code Online (Sandbox Code Playgroud)

如有必要,您还可以考虑使用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');
})
Run Code Online (Sandbox Code Playgroud)

也就是说,如果您几乎总是以相同的方式查询表,则使用自定义函数生成二级索引将显着提高性能.