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

How to add complex constraints in parse?

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)

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

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

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

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

EDIT - 关于一个非常大的析取,我在文档中没有找到任何地方限制 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 的规则,parse 通过提供否定对应物来象征性地处理否定,例如whereEqualTo 可以用 whereNotEqualTo 取反。我很确定这些在功能上并不完整......我偶尔 运行 遇到无法表达我需要的情况。我当时的方法是尽可能少地读取内存并使用应用程序逻辑从那里应用逻辑测试。