How to write a dynamic query with 3 options


#1

Hello, in my code i have a form with 3 FormControl of type select. I am tryng to write a generic query that is generated from the value of the 3 selects but i dont know how to write the corect syntax. here is my code until now:

Meteor.publish('rebatesCount', function rebates(brand, amount, quantity) {
//default values for brand, amount and quantity is ' ' ->  empty string
  check(brand, String);
  check(amount, String);
  check(quantity, Number);



  if (Roles.userIsInRole(this.userId, 'admin')) {
    if (brand === '' && amount === '') {
      return Rebates.find({ brand: { $exists: true }, amount: { $exists: true }, printed: false });
    }
    if (brand !== '' && amount === '') {
      return Rebates.find(
        { brand, amount: { $exists: true }, printed: false },
        { limit: quantity },
      );
    }
    if (brand === '' && amount !== '') {
      return Rebates.find({ amount, printed: false }, { limit: quantity });
    }
    if (brand !== '' && amount !== '') {
      return Rebates.find({ brand, amount, printed: false }, { limit: quantity });
    }
  }
  return null;
});

I know that there must be a better way, the thing i am struggling with is how to say :
give me all rebates with this brand
or all brands and this amount
or this brand and this amount
or this brand, all the amounts, but with this limit … etc.

Thank you.


#2

I don’t know about the empty string, but if you are confident that it is falsey enough, then I’d do something like this. Building up your query should be much cleaner and will also help you escape if/else hell if you need to add more params. This could be a lot more succinct with some ternary operators, but I think clarity is good here:

const query = {};
const options = {};

// brand
if (brand && brand !== '') {
  query.brand = brand;
} else {
  query.brand = { $exists: true };
}

// amount
if (amount && amount !== '') {
  query.amount = amount;
} else {
  query.amount = { $exists: true };
}

// limit
if (quantity && quantity !== '') {
  options.limit = quantity;
}

if (Roles.userIsInRole(this.userId, 'admin')) {
  return Rebates.find(query, options);
}

return [];

#3

thank you so much, now that i see youre code it seems so obvious and easy to do it this way. Thank you again.


#4

You should consider publishing all the data and doing the query on the client if you’re going to be changing it frequently.

I strongly recommend this article to understand the difference between queries on the server and client:


#5

This article from Discover Meteor may be helpful.

http://www.discovermeteor.com/blog/query-constructors/