diff options
| author | Stephen Blott | 2015-05-16 13:18:07 +0100 |
|---|---|---|
| committer | Stephen Blott | 2015-05-16 13:18:07 +0100 |
| commit | fdb41edfeb763cc4805e640ced7a576b7bebe02f (patch) | |
| tree | 356e472a349c6d460165b9b55b52a95ef43800eb | |
| parent | ea2795c37fe8fce95c6ed1e97ae503aac81ee45a (diff) | |
| parent | 87c214ffd80ac436273f35fd95c800589e3f7d4a (diff) | |
| download | vimium-fdb41edfeb763cc4805e640ced7a576b7bebe02f.tar.bz2 | |
Merge pull request #1663 from smblott-github/search-completion-with-regular-relevancy
Search completion with regular relevancy calculation
| -rw-r--r-- | background_scripts/completion.coffee | 50 |
1 files changed, 32 insertions, 18 deletions
diff --git a/background_scripts/completion.coffee b/background_scripts/completion.coffee index da858ca9..ee41aa07 100644 --- a/background_scripts/completion.coffee +++ b/background_scripts/completion.coffee @@ -156,6 +156,12 @@ class Suggestion [ '.', [ "^https?://", "\\W+$" ].map (re) -> new RegExp re ] ] + # Boost a relevancy score by a factor (in the range (0,1.0)), while keeping the score in the range [0,1]. + # This makes greater adjustments to scores near the middle of the range (so, very poor relevancy scores + # remain very poor). + @boostRelevancyScore: (factor, score) -> + score + if score < 0.5 then score * factor else (1.0 - score) * factor + class BookmarkCompleter folderSeparator: "/" currentSearch: null @@ -449,18 +455,9 @@ class SearchEngineCompleter factor = Math.max 0.0, Math.min 1.0, Settings.get "omniSearchWeight" haveCompletionEngine = (0.0 < factor or custom) and CompletionSearch.haveCompletionEngine searchUrl - # Relevancy: - # - Relevancy does not depend upon the actual suggestion (so, it does not depend upon word - # relevancy, say). We assume that the completion engine has already factored that in. Also, - # completion engines sometimes handle spelling mistakes, in which case we wouldn't find the query - # terms in the suggestion anyway. - # - Scores are weighted such that they retain the order provided by the completion engine. - # - The relavancy is higher if the query term is longer. The idea is that search suggestions are more - # likely to be relevant if, after typing some number of characters, the user hasn't yet found - # a useful suggestion from another completer. - # - characterCount = query.length - queryTerms.length + 1 - relevancy = (if custom then 0.5 else factor) * 12.0 / Math.max 12.0, characterCount + # We weight the relevancy factor by the length of the query (exponentially). The idea is that, the + # more the user has typed, the less likely it is that another completer has proven fruitful. + factor *= 1 - Math.pow 0.8, query.length # This filter is applied to all of the suggestions from all of the completers, after they have been # aggregated by the MultiCompleter. @@ -488,15 +485,19 @@ class SearchEngineCompleter forceAutoSelect: custom highlightTerms: not haveCompletionEngine - mkSuggestion = (suggestion) -> + mkSuggestion = (suggestion) => new Suggestion queryTerms: queryTerms type: description url: Utils.createSearchUrl suggestion, searchUrl title: suggestion - relevancy: relevancy *= 0.9 insertText: suggestion highlightTerms: false + isCustomSearch: custom + relevancyFunction: @computeRelevancy + # We reduce the relevancy factor as suggestions are added. This respects, to some extent, the + # order provided by the completion engine. + relevancyData: factor *= 0.95 cachedSuggestions = if haveCompletionEngine then CompletionSearch.complete searchUrl, queryTerms else null @@ -515,11 +516,16 @@ class SearchEngineCompleter onComplete suggestions, filter: filter continuation: (suggestions, onComplete) => - # Fetch completion suggestions from suggestion engines. - # We can skip this if any new suggestions we propose cannot score highly enough to make the list - # anyway. - if 10 <= suggestions.length and relevancy < suggestions[suggestions.length-1].relevancy + # We can skip querying the completion engine if any new suggestions we propose will not score highly + # enough to make the list anyway. We construct a suggestion which perfectly matches the query, and + # ask the relevancy function what score it would get. If that score is less than the score of the + # lowest-ranked suggestion from another completer (and there are already 10 suggestions), then + # there's no need to query the completion engine. + perfectRelevancyScore = @computeRelevancy new Suggestion + queryTerms: queryTerms, title: queryTerms.join(" "), relevancyData: factor + + if 10 <= suggestions.length and perfectRelevancyScore < suggestions[suggestions.length-1].relevancy console.log "skip (cannot make the grade):", suggestions.length, query if SearchEngineCompleter.debug return onComplete [] @@ -527,6 +533,14 @@ class SearchEngineCompleter console.log "fetched suggestions:", suggestions.length, query if SearchEngineCompleter.debug onComplete suggestions.map mkSuggestion + computeRelevancy: ({ relevancyData, queryTerms, title }) -> + # Tweaks: + # - Calibration: we boost relevancy scores to try to achieve an appropriate balance between relevancy + # scores here, and those provided by other completers. + # - Relevancy depends only on the title (which is the search terms), and not on the URL. + Suggestion.boostRelevancyScore 0.5, + relevancyData * RankingUtils.wordRelevancy queryTerms, title, title + # A completer which calls filter() on many completers, aggregates the results, ranks them, and returns the top # 10. All queries from the vomnibar come through a multi completer. class MultiCompleter |
