动态构建RethinkDB过滤器

时间:2015-09-11 13:30:52

标签: rethinkdb reql

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

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查询。

2 个答案:

答案 0 :(得分:1)

抱歉,我理解错了并重新写了我的答案。

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

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

{city: 'London', minAge: 12}

对于城市,我们需要eq,对于minAge,我们需要ge,但由于我们动态地执行此操作,因此提出过滤器对象的语法会更好像这样:

{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。但是我没有看到让RethinkDB上运行的重点,客户端就能做到这一点。

如果有帮助,请告诉我。

答案 1 :(得分: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()函数 - 将使用顺序索引,并且是SLOW。它不能很好地扩展。