RethinkDB - 减少列表字段的结果

RethinkDB - Reduce results of list field

我有一个数据集,其中包含一个包含每个文档的字符串列表的字段。我正在寻找一个查询,它将为我提供该字段中唯一字符串的列表

我认为 reduce 可能是我要找的东西:

r.db('test').table('entity')('listField').reduce(function (left, right) {
  var i;
  var l;
  for (i = 0, l = right.length; i < l; i ++) {
    if (left.not().contains(right[i])) {
      left.append(right[i]);
    }
  }
  return left;
}).default([])

但这只是 returns 列表中第一项的 listField["C", "F", "G"]。 table 中的任何文档都可以在 listField 中包含任意数量的未知值列表。如何获取所有可用值的列表?

你必须记住,客户端脚本不能在 RethinkDB 中工作:这只是两个非常不同的范围。 RethinkDB 只需要您提供一个可以在服务器端计算的 ReQL 表达式。我所说的 ReQL 表达式是指可以在 JavaScript ReQL command reference 中找到的内容,而不是任何类型的客户端语句(语句、赋值、循环、分支等)。 reduce,与所有其他术语类似,可以接受一个函数,该函数可以构建 一个新的 ReQL 表达式 ,并且 并不意味着评估任何与查询。在您的情况下,reduce 函数 returns left 表达式术语(无论您对该术语的操作如何——它们都会创建一个新表达式),这就是您获取文档的原因listField 值。因此,在实际执行查询之前调用表达式构建器函数。

因为你只想找到一个唯一的值,你可以重写查询并轻松使用 RethinkDB 内置函数,如 concatMap and distinct(这些操作非常基本,不仅在 RethinkDB 中):

//r.db('test').table('entity').delete();
//r.db('test').table('entity').insert([{
//  listField: ['A', 'B', 'B', 'C', 'C', 'C', 'C']
//}, {
//  listField: ['B', 'C', 'A', 'Z', 'Z', 'Z']
//}]);

r.db('test')
  .table('entity')
  .concatMap(r.row('listField'))
  .distinct();

你会得到结果:

[
  "A",
  "B",
  "C",
  "Z"
]

上面的查询也可以用表达式构建函数重写:

r.db('test')
  .table('entity')
  .concatMap(row => {
    // your local stuff here that is executed before the query is sent to the server and executed
    // note that this function must return a ReQL expression
    return row.getField('listField');
  })
  .distinct();