Looking into ways to optimise our app and our uses of search and filtering.
I understand search happens on the serverside while filtering is done locally.
In a scenario where we have a large list of Things that need to be filtered based on the tab a user is currently on, is it better to apply a different search with a constraint for each tab, or to first load the data into a ‘master’ search without the constraint and then apply a filter on the master list for each tab ?
I also observed that when applying a filter on the data from a repeating group that has already been loaded, a new pair of msearch/bulk_watch requests are made, which I don’t understand since the filtering is supposed to apply on a list already made available locally ?
does it mean that these both these configurations happen on the server side and have basically the same performance cost/impact? (Considering that in the second image, there’s no constraint on the ‘search for…’ part).
First one is faster and costs less WU because it does the search server side and then returns only the results you want. Hence you load less data.
Second one returns everything within the constraints of your privacy settings and then filters the search results client side. So you load more data and then add the client-side overhead for the filtering.
As a general rule i avoid putting a search as a data source and opt to put data into a state.
Here’s something i posted that you may be interested in:
That should be true only if you are using advanced filtering or if you have something between do a search and :filtered
But if it’s not the case (as in OPs example above) - the number of searches and fetched items should be the same as I remember .
All :filtered operations run client-side and apply after the search. The final results are the same but the search returns more data.
You can check this in the debugger and the browser inspector.
From the manual:
Filters a list of things with a criteria. It’s similar to a search but happens after the search and can also be used on a field that is a list of things. The filtering constraints work similarly to a search constraint.
I personally avoid using :filtered until I need advanced filtering to compare lists and remember that Bubble states :filtered is performed after the search (aka client-side). But somehow not long ago while testing one of my apps I’ve discovered that it’s not always true (or I am missing something).
So, I have 4048 cats in my DB. Only 11 cats are relevant for my constraint (age < 10). This 11 cats are distributed among first 300-400 rows of the DB.
I’ve tested with 2 approaches:
I make it a practice to only use states as RG data sources, so I know that performance is great even for large data sources.
It’s been a while since I’ve used a search as a data source in an RG but one can assume that each time your RG switches data sources from one search to another that the first time the data source is called, there will be a load time but subsequently it’ll be much faster cause the results have already been loaded and cached by Bubble.
The difference I do know is that there’s a WU overhead for Real-time Search for every active data source using a search.
That’s what we are trying to figure out)
Bubble official documentation and most part of the community (including OGs with tons of experience) states that :filtered is always applied client side after the search.
I was in the same boat for a long time but a random experiment I’ve performed not long ago resulted in :filtered being applied server side (excluding Advanced filtering which is still client side).
So now I’m looking forward to get a reply from Bubble support.
Btw, here is an interesting quote from Petter (author of “The Ultimate Guide to Bubble Performance” book):
Thanks for posting! The difference that you bring up about :filters being performed server-side/client-side was one of the major revisions of the second edition of the book, and if that’s the version you’re referring to it may not be clear enough still (I can’t check the book right now, but thanks for including page numbers).
In the first edition, filters were described as being performed client-side more or less without exception, but it should have been made clear that this will normally only apply to advanced filters (or filters applied to an already completed search). Whenever a :filter is applied to a fresh search Bubble will attempt to perform the full query on the server and in many (probably most) cases it can.
So it would be great if @petter could confirm if it’s still a thing.
So, I was lucky enough to get some quick communication with Bubble App Design team support member within an bug report.
The short conclusion is - basic filtering (using almost all options available inside :filtered operator except Advanced...) is performed:
server-side: if it is a part of data fetching (for example, if it is a part of Do a search for:filtered expression when we are expecting to get some data from the database)
client-side: if we are filtering data that has been already fetched beforehand (for example, if we have a custom state that has been already populated with data from the database and we are referencing it in a repeating group with an expression like Custom State:filtered).
So this fully matches information from Petter’s post I’ve mentioned in my previous post above.