Fastest Filtering Method


#1

I have a simple app that utilizes an ember data model and a input field to search for and display matches. On load the page is drawn with each model in a series of rows (roughly a thousand). On each keyup, I take the query from the search box, make a regex and loop over the model to see which have a fullName property that passes the /query/.test(). If it passes, I set a flag of shouldShowInList to true.

I’ve tried a few different methods like using an {{if model.shouldShowInList}} to draw the row with the model. As well as using the same flag for adding a hidden class on the row markup like so {{if model.shouldShowInList 'is-hidden'}}.

After some profiling, I found that adding the ‘is-hidden’ class is remarkably faster however the filtering can still slow the app down to a crawl, especially when deleting the query since this is when the DOM is being reloaded with all of the model.

I’m wondering what other people have found to be the quickest way to perform a model filtering on the front-end for a similar situation?


#2

I’d seriously consider whether loading and rendering ~1000 rows is a good idea. You’re making the user wait a comparatively long time to fetch that data and for the browser to render it.

I’d consider loading less data and either using pagination or something like smoke and mirrors to only render the rows that are in the viewport.


#3

When the user is typing in the search box, the app will slow to a crawl while it attempts to recalculate on every key press.

To help with performance while searching, you can debounce your computed property so that it doesn’t recalculate on every key press. If you debounce by around 200ms to 300ms then it will calculate the search when the user briefly pauses typing.


#4

@ricky1981 yes I think pagination is where I’m headed with the app. This will undoubtedly be a faster initial load but I still have to do some filtering - hiding/drawing method on the model which is what I’m really asking the community for advice on.

@LozJackson I forgot to mention that I am already using Ember.run.throttle on the search box. This counts down on the calculation cycles, but its really the redrawing of the DOM that ends up taking the longest time.

How do you guys handle large amounts of filtering/redrawing?


#5

There are lots of cases when you need highly responsive filtering in response to user behavior, and relying on the server can add network latency and large numbers of requests.

1k items doesn’t need to be slow to filter at all.

I’d suggest you try a couple things. First, instead of putting the conditional in the template, create a filtered CP in your js instead that computes based on the changes to your query.

The CP would return an array of valid items and use the filter() function.

filteredData: Ember.computed('rawData.[]','query', function(){
    var data=this.get('data'),
    query=this.get('query');

    return data.filter( anItem => anItem.indexOf(query) > -1));
}

Then just each over filteredData In your template.

If you have a variety of queries you need to validate to filter, and if your data set is very large, first cull it down to a smaller set. Do that by applying The filter that will remove the most items first, then apply succesively complex queries so that those are only occurring on otherwise valid records.

Sorry if the code isn’t quite proper, I’m typing on a phone… :slight_smile: