Skip to content

Commit

Permalink
Merge pull request #815 from HubSpot/new_fuzzy_search
Browse files Browse the repository at this point in the history
New fuzzy search algorithm for better results and perf
  • Loading branch information
Tom Petr committed Dec 29, 2015
2 parents b1f31be + 617c248 commit 2a77487
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 21 deletions.
12 changes: 5 additions & 7 deletions SingularityUI/app/views/globalSearch.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,11 @@ class GlobalSearchView extends View

@lastSearchQuery = query

fuse = new Fuse(
@requests.toJSON()
keys: ["request.id"]
threshold: 0.6
id: "request.id"
maxPatternLength: 128)
results = fuse.search(query)
options =
extract: (o) ->
o.id
res = fuzzy.filter(query, @requests.toJSON(), options)
results = _.pluck(_.pluck(_.sortBy(res, (r) => r.score).reverse(), 'original'), 'id')

process results.slice(0, 10)

Expand Down
22 changes: 13 additions & 9 deletions SingularityUI/app/views/requests.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -50,22 +50,26 @@ class RequestsView extends View
@bodyTemplate = @bodyTemplateMap[@state]
@listenTo @collection, 'sync', @render

# So we don't spam it with every keystroke
@searchChange = _.debounce @searchChange, 200
@fuzzySearch = _.memoize(@fuzzySearch)

fuzzySearch: (filter, requests) =>
id =
extract: (o) ->
o.id
user =
extract: (o) ->
o.requestDeployState?.activeDeploy?.user or ''
res1 = fuzzy.filter(filter, requests, id)
res2 = fuzzy.filter(filter, requests, user)
_.pluck(_.sortBy(_.union(res1, res2), (r) => r.score), 'original')

# Returns the array of requests that need to be rendered
filterCollection: =>
requests = _.pluck @collection.models, "attributes"

# Only show requests that match the search query
if @searchFilter
searchFilter = @searchFilter.toLowerCase().split("@")[0]
fuse = new Fuse(
requests
keys: ["request.id", "requestDeployState.activeDeploy.user", "request.owners"]
threshold: 0.4
maxPatternLength: 128)
requests = fuse.search(searchFilter).reverse()
requests = @fuzzySearch(@searchFilter, requests)

# Only show requests that match the clicky filters
if @state in @haveSubfilter and @subFilter isnt 'all'
Expand Down
18 changes: 14 additions & 4 deletions SingularityUI/app/views/tasks.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,27 @@ class TasksView extends View
@listenTo @cleaningTasks, 'change', @render
@listenTo @taskKillRecords, 'change', @render

@searchChange = _.debounce @searchChange, 200
@fuzzySearch = _.memoize(@fuzzySearch)

fuzzySearch: (filter, tasks) =>
host =
extract: (o) ->
"#{o.host}"
id =
extract: (o) ->
"#{o.id}"
res1 = fuzzy.filter(filter, tasks, host)
res2 = fuzzy.filter(filter, tasks, id)
_.pluck(_.sortBy(_.union(res1, res2), (r) => r.score), 'original')

# Returns the array of tasks that need to be rendered
filterCollection: =>
tasks = _.pluck @collection.models, "attributes"

# Only show tasks that match the search query
if @searchFilter
tasks = _.filter tasks, (task) =>
searchField = "#{ task.id }#{ task.host }".toLowerCase().replace(/-/g, '_')
searchField.toLowerCase().indexOf(@searchFilter.toLowerCase().replace(/-/g, '_')) isnt -1
tasks = @fuzzySearch(@searchFilter, tasks)

# Sort the table if the user clicked on the table heading things
if @sortAttribute?
tasks = _.sortBy tasks, (task) =>
Expand Down
2 changes: 1 addition & 1 deletion SingularityUI/bower.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
"datatables": "~1.10.7",
"datatables-bootstrap3-plugin": "~0.4.0",
"select2": "~3.5.2",
"fuse.js": "~1.2.2"
"fuzzy": "~0.1.1"
},
"resolutions": {
"backbone": "~1.1.2",
Expand Down

0 comments on commit 2a77487

Please sign in to comment.