Statistics with search conditions

Hello,
I am currently looking to display vouchers from a collection (called “bonsNuitees”) and statistics based on a search. I have the following code for the moment :

Template.bonsListe.helpers({
    bons(){
        return BonsNuitees.find({
            "beneficiaires.nomB": { $regex: Session.get('prefixBenef')+".*", $options: 'i' },
            "beneficiaires.typologieB": { $regex: Session.get('typoBenef') },
            "beneficiaires.tranchAge": { $regex: Session.get('tranchAgeBenef') },
            $or: [
                { $and: [ {date_debut: { $gte: Session.get('dateDebut')}}, {date_fin: { $lte: Session.get('dateFin')} } ] },
                { $and: [ {date_debut: { $lt: Session.get('dateDebut')}}, { $and: [ {date_fin: {$lte: Session.get('dateFin')}}, {date_fin: {$gte: Session.get('dateDebut')}}] } ] },
                { $and: [ { $and: [ {date_debut: {$gte: Session.get('dateDebut')}}, {date_debut: {$lte: Session.get('dateFin')}}] }, {date_fin: { $gt: Session.get('dateFin')}} ] },
                { $and: [ {date_debut: { $lt: Session.get('dateDebut')}}, {date_fin: { $gt: Session.get('dateFin')} } ] }
                ],
        });
    },
});

Template.bonsListe.events({
    'click .btn-recherche-bon': function() {
        Session.set('prefixBenef', $('.beneficiaireNom').val());
        Session.set('typoBenef', $('.beneficiaireTypo').val());
        Session.set('tranchAgeBenef', $('.beneficiaireTranchAge').val());
        Session.set('dateDebut', $('.date_debut').val());
        Session.set('dateFin', $('.date_fin').val());
    },
});

A voucher has a start date (“date_debut”) and an end date (“date_fin”). During a search we enter a period. It displays the vouchers whose period is included in the searched period. I would like to display the number of days from vouchers. I need to count days corresponding to the following conditions :

  • if (date_start >= date_start_search) && (date_end <= date_end_search) { nbDays=nbDays+(date_end-date_start) }
  • if (date_start < date_start_search) && ((date_end <= date_end_search) && (date_end >= date_start-search)) { nbDays=nbDays+(date_end-date_start_search) }
  • if ((date_start >= date_start_search) && (date_start <= date_end_search)) && (date_end > date_end_search) { nbDays=nbDays+(date_end_search-date_start) }
  • if (date_start < date_start_search) && (date_end > date_end_search) { nbDays=nbDays+(date_end_search-date_start_search) }

I am a beginner in meteor and mongo so I don’t know how to proceed. Could you help me please ?

I’ll try to answer this as much as I understand the request. Let me start with an opinion, if you are new to Meteor, drop Blaze and do things in React.

In Blaze, as far as I can remember you have something like this:

const brief_or_selection_or_forms_or_else = {
      fieldOne: tmpl.find('#field-one').value || 'defaultValueOne',
      fieldTwo: tmpl.find('#field-two').value || 'defaultValueTwo',
      ...
    }

Now, you take this object (without saving into Session.keys) and pass it through a Meteor Method.
Grab it on the server and return the result. You only return data that you need to work with on the client side, I guess for you that would be intersection of valid vouchers date range with search range.
In the UX side you condition the two fields so that dateDebut is alway smaller than dateFin (or equal if same day) just to make sure users cannot make any mistake.
For the query I am thinking, if any of dateDebut and dateFin is in between your search range, that is a hit.
So I would say your date query could be

...
date_debut: { $lte: dateFin },
date_fin:  { $gte: dateDebut }
...
// and you know already dateDebut is always <= dateFin 

I am not sure if this is covering everything, but … !!!
Then on the client you get [ … objects with dates with valid vouchers ]. Map through the array and calculate the days. You can do this both on the client or on the server (within the method before return to client) but ideally this should be in a helper on the client. Perhaps something like:

   myFinalResultsWithNoDays = []  /* use this array to build your list in UI */
   myBonsNuitees.map(result => {
     result.nbDays = Math.min(date_end, date_end_search) - Math.max(date_start, date_start_search)
          // this gives you the intersection between the voucher range and the search range.
          // not sure but I guess if the result is 0, this means one day.
     delete keys_on result_you_dont_need_if_any
     myFinalResultsWithNoDays.push(result)
   }
)

I did not test any of these, nor used in any code it is all written mathematically so I might be totally wrong. Nevertheless this simple your could should look.
For all those search queries, make sure you have indexes created on the Collection.

Hello,
Thank you for your help. I finally managed to do it by using find().fetch().foreach(“conditions here”) in the helper. I suspect this is not the most optimized solution, but I’m running out of time. I will try to optimize afterwards if ever I can.

This is doing your filtering on the server which is cool as long as your server’s CPU can take the load (depending in the number of users/calls). This is why I personally favor doing computations on the client’s end. Best of success on your project!