Search code examples
parse-platform

Parse Javascript SDK query: Combining two queries using AND


I have a class named Event, it has a column named end_time of type Date and a column named title of type String. I would like to fetch the events whose end_time column is either undefined or is greater than or equal to new Date(). This is not difficult as it can be done with the following code:

var query1 = new Parse.Query(Event);
var query2 = new Parse.Query(Event);
query1.doesNotExist("end_time");
query2.greaterThanOrEqualTo("end_time", new Date());

var query1And2 = Parse.Query.or(query1, query2);

query1And2 can correctly return the results I want. However, the problem is if I add one more constrain like: given a user specified title, return the events whose title is either undefined or equals user specified title. This constrain is not difficult to construct in its own, like:

var query3 = new Parse.Query(Event);
var query4 = new Parse.Query(Event);
query3.doesNotExist("title");
query4.equalTo("title", userTitle);

var query3And4 = Parse.Query.or(query3, query4);

but, how can I query Event with both query1And2 and query3And4?


Solution

  • These constraints can be achieved with a little boolean math. It looks like you already understand that parse allows you to specify conjunctive (and) constraints on a single query and disjunctive (or) constraints by combining multiple queries with Query.or()**. So to get the constraints you're aiming for, we need to transform your query logic to disjucntive form.

    Your individual predicates are:

    A = doesNotExist("end_time")
    B = greaterThanOrEqualTo("end_time", new Date())
    C = doesNotExist("title")
    D = equalTo("title", userTitle)
    

    and we wish to produce the query:

    (A or B) and (C or D)
    

    Rewriting this product of sums as a sum of products using algebra, we get:

    = (A and C) or (B and C) or (A and D) or (B and D)
    =    q0     or    q1     or    q2     or    q3
    

    where q0..q3 are queries constrained by ANDed constraints. Rendering those as code:

    var q0 = new Parse.Query(Event);
    q0.doesNotExist("end_time");
    q0.doesNotExist("title");
    
    var q1 = new Parse.Query(Event);
    q1.greaterThanOrEqualTo("end_time", new Date());
    q1.doesNotExist("title");
    
    var q2 = new Parse.Query(Event);
    q2.doesNotExist("end_time");
    q2.equalTo("title", userTitle);
    
    var q3 = new Parse.Query(Event);
    q3.greaterThanOrEqualTo("end_time", new Date());
    q3.equalTo("title", userTitle);
    
    var querySum = Parse.Query.or(q0, q1, q2, q3);
    

    ** Query.or() probably just runs those queries separately they way we would with Promise.when() and combines the results, but lets assume that parse does a better job at this than we can at the app level.