如何在解析中添加复杂约束?

时间:2015-02-12 00:20:21

标签: android parse-platform constraints

Parse的文档解释了如何使用OR运算符添加多个约束,使用此示例。

ParseQuery<ParseObject> lotsOfWins = ParseQuery.getQuery("Player");
    lotsOfWins.whereGreaterThan(150);

    ParseQuery<ParseObject> fewWins = ParseQuery.getQuery("Player");
    fewWins.whereLessThan(5);

    List<ParseQuery<ParseObject>> queries = new ArrayList<ParseQuery<ParseObject>>();
    queries.add(lotsOfWins);
    queries.add(fewWins);

    ParseQuery<ParseObject> mainQuery = ParseQuery.or(queries);
    mainQuery.findInBackground(new FindCallback<ParseObject>() {
      public void done(List<ParseObject> results, ParseException e) {
        // results has the list of players that win a lot or haven't won much.
      }
    });

但我想在Conjunctive normal form中添加多个OR运算符。得到这样的东西:(a OR b OR c)AND(d OR e OR f)AND(g OR h OR i)

有什么方法可以做到这一点吗?

1 个答案:

答案 0 :(得分:0)

它肯定不是sql,但是在同一查询中支持AND作为复合条件,并且使用Query.or方法支持OR。换句话说,冒着过于笼统的风险,将你的逻辑转换为析取形式:

(a OR b) AND (c OR d) = (a AND c) OR (b AND c) OR (a AND d) OR (b AND d)

并为每个析取操作数构建查询,每个操作数都应用了多个连接操作数。

编辑 - 关于一个非常大的析取,我在文档中找不到OR允许的查询操作数的限制,但是有意义的是存在限制并且解析会使它变小。

当您用尽query.or限制时,可以通过串行运行批处理并对结果求和来实现析取。换句话说,将查询分组为10或其他,使用OR连续运行它们,每次将结果添加到排除重复项的累积集中。

但无论你如何对其进行分割,非常复杂的条件都会导致计算开销,这些开销会在某些时候遇到资源限制(一些人为基于你正在使用的薪酬等级)。

例如,假设您从上面的谓词开始,并且您已将其转换为析取形式,就像我一样。比如说,Query.or仅限于2个查询。您仍然可以按顺序执行两个或两个,并将结果汇​​总(如js):

var queryAC = new Parse.Query("MyClass");
// set queryAC.whereEqualTo(), where... for constraint a
// set queryAC.whereEqualTo(), where... for constraint c

var queryBC = new Parse.Query("MyClass");
// set queryAC.whereEqualTo(), where... for constraint b
// set queryAC.whereEqualTo(), where... for constraint c

var queryAD = new Parse.Query("MyClass");
// set queryAC.whereEqualTo(), where... for constraint a
// set queryAC.whereEqualTo(), where... for constraint d

var queryBD = new Parse.Query("MyClass");
// set queryAC.whereEqualTo(), where... for constraint b
// set queryAC.whereEqualTo(), where... for constraint d

// now, run them as or, serially.  in JS using promises...
var cumulativeResults = [];
Parse.Query.or(queryAC, queryBC).then(function(results) {
    cumulativeResults = cumulativeResults.concat(results);
    return Parse.Query.or(queryAD, queryBD);

    // this is how to do it in js with promises, in Java, the 
    // equivalent idea is to run the next or in the completion
    // callback of the first one
}).then(function (results) {
    cumulativeResults = cumulativeResults.concat(results);
    // remove dups here based on objectId, or do it in the line
    // above when adding results.
    // now cumulativeResults contains the OR sum of the original expression
});

关于应用deMorgan的规则,解析通过提供否定对应物来象征性地处理否定词,例如: whereEqualTo可以否定whereNotEqualTo。我很确定这些都不是功能完整的...我偶尔会遇到无法表达我需要的情况。我在这一点上的方法是尽可能少地读入内存并使用app逻辑从那里应用逻辑测试。