2

我想使用如下指定的过滤器过滤我的数据:

var filter = { minAge: 2, maxAge: 11, country:'uk', city':'london'};

在这种情况下,过滤将是:

r.db(dbName).table(tableName)
    .filter(r.row("minAge").ge(filter.minAge)
             .and(r.row("maxAge").le(filter.maxAge))
             .and(r.row('country').eq(filter.country))
             .and(r.row('city').eq(filter.city))
           );

但是,某些过滤谓词可能会丢失,例如,如果我只有最小年龄和城市,我只想过滤它们:

var filter2 = { minAge: 2, city':'london'};

上面的过滤器应该导致下面

r.db(dbName).table(tableName)
    .filter(r.row("minAge").ge(filter.minAge)             
             .and(r.row('city').eq(filter.city))
           );

如何根据我可以传递给过滤器函数的过滤器对象键构建 ReQL 查询。

4

3 回答 3

2

对不起,我理解错了,重新写下我的答案。

我认为您可以做的是编写一个在客户端上运行以返回过滤器查询的通用函数。

首先,如果您正在动态处理过滤器对象,则过滤器函数不知道要应用哪个操作。鉴于这种:

{city: 'London', minAge: 12}

对于 city 我们想要 a eq,因为minAge我们想要 age但由于我们是动态执行此操作的,因此最好为 filter 对象提出如下语法:

{city: 'London', minAge: ['ge', 12]}

考虑到这一点,我提出了这个解决方案:

var filterObject = {
  minAge: ['ge', 12],
  city: 'london'
}

r.table('monitor').filter((function(filterObject) {
  var condition

  for (var key in filterObject) {
    var conditionForThisKey
    if (typeof key == 'string' || typeof key == 'number') {
      conditionForThisKey = r.row(key).eq(filterObject[key])
    } else {
      conditionForThisKey = r.row(key)[filterObject[key][0]](filterObject[key][1])
    }

    if (typeof condition === 'undefined') {
      condition = conditionForThisKey
    } else {
      condition = condition.and(conditionForThisKey)
    }
  }

  return condition
})(filterObject))
.run(connection)
.then(function(cursor){ //do stuff with result })
.error(function(err) { //err handling })

这样,我们在客户端动态地为 RethinkDB 构建条件对象。我在想我们可以用r.js. 但是我看不出让它在 RethinkDB 上运行的意义,客户端有能力做到这一点。

让我知道这是否有帮助。

于 2015-09-11T20:03:40.700 回答
0

避免通过缺少字段进行过滤的一个适度肮脏的技巧是只添加默认值 -

r.db(dbName).table(tableName)
   .filter(r.row("minAge").default(filter.minAge).ge(filter.minAge)
      .and(r.row("maxAge").default(filter.maxAge).le(filter.maxAge))
      .and(r.row('country').default(filter.country).eq(filter.country))
      .and(r.row('city').default(filter.city).eq(filter.city))
   );

它效率不高,也不是很好,但是如果您暂时不想过度设计它,它应该可以工作。

请注意,顺序扫描——在查询早期没有使用限制的查询,或者没有任何索引的查询,只对整个表使用 .filter() 函数——将使用顺序索引,并且速度很慢。它不能很好地扩展。

于 2017-06-08T13:53:42.400 回答
0

如果有人在寻找解决方案,这里有一个来自维护者 (srh) 的解决方案。

RethinkDB 查询只是对象,您可以创建通用函数来为您构建它们。

    function makeFilterExpr(x, obj) {
      let expr = r.expr(true);
      if ('minAge' in obj) { expr = expr.and(x('age').ge(obj['minAge'])); }
      if ('city' in obj) { expr = expr.and(x('city').eq(obj['city'])); }
      return expr;
    }
    
    // usage:
    let query = r.table('foo').filter(x => makeFilterExpr(x, {'minAge': 2, 'city': 'London'}));

您只需要编写进行查询的代码。

于 2022-02-16T19:29:59.220 回答