2

I'm trying to create an or query from an array of queries. I need to use an array because the amount of queries isn't fixed, it depends on a user input.

This is some sample code from parse.com to implement an or query.

var lotsOfWins = new Parse.Query("Player");
lotsOfWins.greaterThan("wins", 150);

var fewWins = new Parse.Query("Player");
fewWins.lessThan("wins", 5);

var mainQuery = Parse.Query.or(lotsOfWins, fewWins);
mainQuery.find()
  .then(function(results) {
    // results contains a list of players that either have won a lot of games or won only a few games.
  })
  .catch(function(error) {
    // There was an error.
  });

What I'm trying to do is

var orQueries = [];

Filling the array within a for-loop with Parse.Query Objects. Then I'm calling

var userQuery = new Parse.Query.or(orQueries);

which causes a internal server error:

"TypeError: A ParseQuery must be constructed with a ParseObject or class name.

How can I solve this issue and initialize the query with an array?

1
  • 1
    Ohh, scrap the new. Parse.Query.or isn't a constructor, it's a method that returns a query for you. That being said you may still have a problem with passing an array instead of comma separated arguments. Commented Mar 6, 2018 at 23:10

2 Answers 2

4

One answer is to use JS to apply the arguments like this...

// In older JS:
var orQueries = [lotsOfWins, fewWins];
var querySum = Parse.Query.or.apply(null, orQueries);

// >=ES6:
var orQueries = [lotsOfWins, fewWins];
var querySum = Parse.Query.or(...orQueries);

I don't know the upper limit for the length of the query array, but you should take care not to put that fully under user control.

EDIT - If the queries are few in number and produce reasonably small results sets (like under 1k total?) you could forgo Query.or and do the "or" work yourself...

const _ = require('underscore');

function disjunctiveQuery(queries) {
    return Promise.all(queries).then(results => _.uniq(_.flatten(results), 'id'));
}

disjunctiveQuery([queryA, queryB, queryC, queryD]).then( ...
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you, I'll try It right now :) The upper limit is 4, but thanks for the hint!
@Steeve, you bet. Probably only for instructive purpose, added an approach that bypass Query.or in favor of app code that does something equivalent.
1

If @danh's answer doesn't work, one workaround you can do is to use Parse.Promise.when().

This takes in an array of promises, and returns the results of every promise, once every promise has completed. For queries, that means you'll end up with an array of arrays, and you'll have to discern what is what yourself (perhaps have a separate array of query identifiers to keep track?)

var promises = [];

if( needToPerformQuery0 ) {
    var query0 = new Parse.Query("MyClass");
    // Set up query
    var promise = query0.find();
    promises.push(promise);
}

if( needToPerformQuery1 ) {
    var query1 = new Parse.Query("MyClass");
    // Set up query
    var promise = query1.find();
    promises.push(promise);
}

return Parse.Promise.when(promises).then(
    function( results ) {
        if( success.count > 0 ) {
             result0 = results[0];
             //Do something
        }
    },
    function( errors ) {
        console.log("There was at least one error: " + JSON.stringify(errors));
    }
);

1 Comment

Good point. I suggested something similar in that second block of code in my answer. I think Parse.Promise.when() and Promise.all() are synonymous. Underscore is a nice way to "flatten" the array of array of results.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.