How to Filter by time of day?

I have an index of restaurants and I’d like to allow users to filter for restaurants that are currently open.

A restaurant may be open for 3 hours in the morning, then close for a few hours, then re-open for dinner.

Is there a canonical way to do this in Algolia?

I had the following potential datamodel in mind:

hours: {
  monday: [{ 
    // morning hours
    start: minute_of_day, 
    end: minute_of_day, 
  }, { 
    // evening hours
    start: minute_of_day, 
    end: minute_of_day, 
  }],
  ...
}

I would then need to be able to filter with this sort of logic:

for range in restaurant.hours.monday {
  if current_minute_of_day > range.start &&  current_minute_of_day < range.end
    return true
}
return false

Is this possible in Algolia, or is there another way to accomplish this?

Hi @netbkb,

Thanks for contacting Algolia with your question!

In general, you’ll be creating a record structure that you “make up” and works best for you, but let’s think through it a bit below.

In Algolia, we do have the concept of “filtering by date” with a UNIX timestamp. However, we already know that this includes the time and date and therefore it is too specific for your needs.

You need a model that works only for time, that is independent of the date.

My suggestion is to consider an approach where:

  • Create own measurement - Create a measurement that accounts for an entire day in seconds, therefore a whole day could be: integer 86,400 (equivalent to total seconds, 24 hrs * 60 mins * 60 secs)
  • Create attributes - For each record create attributes that map to this integer: for example a start time of 9am would be: 32,400 (9 hours * 60 mins * 60 secs); and an end time of 5pm would be: 61,200 (17 hours * 60 mins * 60 secs)

Your sample record might look like:

    {
        "name": "my restaurant",
        "start_time": 32,400,
        "end_time": 61,200
     }
  • Get Current Time - The next consideration would be: How do I get my current_time from my end-user and translate it into this “made up” measure? We don’t have this answer for you. It would have to account for timezones, etc., and we’d rely on you to come up with this approach.
  • Use Algolia - Once you have the current_time you can leverage Algolia filters as you already imagined:
index.search({
  query: 'restaurant',
  filters: 'start_time < current_time AND current_time < end_time'
}).then(res => {
  // console.log(res);
});

Hey @ajay.david,

There was an additional requirement in my question that wasn’t addressed as part of your answer, and this additional requirement is what I am unsure about.

It’s the part where a single restaurant might be open for two or more non-continuous time ranges per day. For example, a restaurant might only be open between 9am - 12pm, and 5pm - 10pm. In this case, the solution you proposed would not be enough, and there would need to be an array of objects that contain start_time and end_time. I would then need to be able to query for restaurants that have at east one entry in this array that matches the user’s current time.

Is this possible?

Thanks for your help!

Hey @netbkb,
ah yes! This adds another layer of complexity to things. What I would recommend is actually duplicating any records that have multiple non-continuous opening times. So let’s say Joe’s restaurant is open from A - B and C - D. This would result in two records that would looks like:

{
“name”: “Joe’s”,
“start_time”: A
“end_time”: B,
“display_opening_times”: “A - B and C - D”
},
{
“name”: “Joe’s”,
“start_time”: C,
“end_time”: D,
“display_opening_times”: “A - B and C - D”
}

You would use the "display_opening_times to actually show the opening times on the front-end, but using the “start_time” and “end_time” to do filtering like

{“filters”:“start_time < current_time AND end_time > current_time”}

Finally, to deduplicate and only ever show one record per restaurant at a time (if for some reason the “now” pulls up multiple records for the same restaurant), you could use the distinct feature. When using distinct, you first need to set an attributeForDistinct to deduplicate on. In this case “name” would work.

Does that seem like it would work for you?

1 Like

That’s a great suggestion @maria.schreiber - I agree, the route to go is:

  • duplicate records for the restaurant, where each record has a different set of start_time and end_time
  • use attributeForDistinct to de-duplicate

This leverages Algolia as it was designed to be used

Hey Maria, thanks for chiming in.

This solution doesn’t work for me because attributeForDistinct on this index is already in use by another attribute that is more important. Are there any other possible solutions?

Hi @netbkb,

If I understand what you are trying to do, I believe one option would be to restructure your data like this:

{
  "hours": {
    "monday": [
      {
        "morningStart": 7,
        "morningEnd": 12
      },
      {
        "eveningStart": 16,
        "eveningEnd": 23
      }
    ]
  }
}

You would need a filter that won’t actually work with Algolia because it would slow your search down quite a bit:

{ "filters": "(hours.monday.morningStart < 11 AND hours.monday.morningEnd > 11) OR (hours.monday.eveningStart < 11 AND hours.monday.eveningEnd > 11" }

For performance reasons, filter expressions are limited to a conjunction (ANDs) of disjunctions (ORs). In other words, you can have ANDs of ORs (e.g. filter1 AND (filter2 OR filter3) ), but not ORs of ANDs (e.g. filter1 OR (filter2 AND filter3) .

In your case, to get around this issue, you could check your time to see if it’s a morning time or an eventing time and then apply the correct filter:

If (time < noon) {
   apply this filter `{ "filters": "hours.monday.morningStart < time AND hours.monday.morningEnd > time" }`
} else {
   apply this filter `{ "filters": "hours.monday.eveningStart < time AND hours.monday.eveningEnd > time" }`
}

Of course you would need to some extra processing for the different days of the week.

Hi Cindy,

Thanks so much and thank you @ajay.david and @maria.schreiber for your help. Creative solutions like this do a good job of convining that Algolia has an awesome team :slight_smile:

3 Likes