Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
fbb62cf
Boost title-matching scores if main title
wlach May 25, 2024
96e2894
[search] Add fixture data for use with title relevance test cases.
jayaddison Jun 18, 2024
a2a4b60
[search] tests: add test coverage for title-related relevance scoring.
jayaddison Jun 19, 2024
cb0f6e7
[search] regenerate JS fixture root titles searchindex from fresh/cle…
jayaddison Jun 19, 2024
75eaf81
Merge branch 'master' into issue-12391/subtitle-search-scoring-adjust…
jayaddison Jun 23, 2024
0f0624e
Merge branch 'boost-scores-if-main-title' into issue-12391/subtitle-s…
jayaddison Jun 24, 2024
5eaea64
[search] Refactor scoring logic adjustment:
jayaddison Jun 24, 2024
afb1685
Add CHANGES.rst entry.
jayaddison Jun 24, 2024
5a5e271
Fixup: add missing credit to CHANGES.rst
jayaddison Jun 24, 2024
5c106c8
Merge branch 'master' into issue-12391/subtitle-search-scoring-adjust…
jayaddison Jun 24, 2024
7418a71
Fixup: use intended operator precedence.
jayaddison Jun 24, 2024
17367eb
Revert "Fixup: use intended operator precedence."
jayaddison Jun 25, 2024
96526a9
Revert "[search] Refactor scoring logic adjustment:"
jayaddison Jun 25, 2024
6c3ffa2
[search] Refactor scoring logic adjustments (second attempt/suggestion)
jayaddison Jun 25, 2024
fd36010
Fixup: adjust test search result score expectation.
jayaddison Jun 25, 2024
c259b1c
Merge branch 'master' into issue-12391/subtitle-search-scoring-adjust…
jayaddison Jul 6, 2024
7f8a5f6
Merge branch 'master' into issue-12391/subtitle-search-scoring-adjust…
jayaddison Jul 8, 2024
2f0cbe1
Tests: refactor checkRanking function to use JavaScript array-unpacking.
jayaddison Jul 8, 2024
bf576cd
Tests: refactor checkRanking function to use JavaScript ``for...of`` …
jayaddison Jul 8, 2024
d1a7197
Tests: add early-exit path to checkRanking function.
jayaddison Jul 8, 2024
5d5b079
Tests: extract two distinct relevance-related test cases from existin…
jayaddison Jul 8, 2024
e9bdf2f
Tests: nitpick: reverse the ``results`` array instead of reversing th…
jayaddison Jul 8, 2024
e75891e
Regenerate JS test search fixtures using ``utils/generate_js_fixtures…
jayaddison Jul 8, 2024
d5d8717
Tests: update expectations since main titles now have empty anchor ta…
jayaddison Jul 8, 2024
388aef3
Code review: apply phrasing/typo-fixup suggestions.
jayaddison Jul 9, 2024
4d819cc
Value-safety: use ``const`` for scoring variables.
jayaddison Jul 9, 2024
9d59eaf
Tests: self-documentation: add comment to describe the purpose of the…
jayaddison Jul 9, 2024
7b772a2
Code review feedback: add class-level attribute with same name as a (…
jayaddison Jul 9, 2024
4e07078
Tests: split object-vs-title matching into two distinct rules.
jayaddison Jul 10, 2024
1b42e80
Merge branch 'master' into issue-12391/subtitle-search-scoring-adjust…
jayaddison Jul 10, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ Bugs fixed
* #12459: Add valid-type arguments to the ``linkcheck_rate_limit_timeout``
configuration setting.
Patch by James Addison.
* #12391: Adjust scoring of matches during HTML search so that document main
titles tend to rank more highly than subsection titles, and also to provide
a gain to matches on the name of programming domain objects relative to
title/subtitle matches.
Patch by James Addison and Will Lachance.

Improvements
------------
Expand Down
3 changes: 2 additions & 1 deletion sphinx/themes/basic/static/searchtools.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ if (typeof Scorer === "undefined") {
objPrioDefault: 0,

// query found in title
mainTitle: 16,
title: 15,
partialTitle: 7,
// query found in terms
Expand Down Expand Up @@ -328,7 +329,7 @@ const Search = {
for (const [title, foundTitles] of Object.entries(allTitles)) {
if (title.toLowerCase().trim().includes(queryLower) && (queryLower.length >= title.length/2)) {
for (const [file, id] of foundTitles) {
let score = Math.round(100 * queryLower.length / title.length)
let score = Math.round((titles[file] !== title ? Scorer.title : Scorer.mainTitle) * queryLower.length / title.length)
normalResults.push([
docNames[file],
titles[file] !== title ? `${titles[file]} > ${title}` : title,
Expand Down
1 change: 1 addition & 0 deletions tests/js/fixtures/titles/searchindex.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions tests/js/roots/titles/conf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import os
import sys

sys.path.insert(0, os.path.abspath('.'))

extensions = ['sphinx.ext.autodoc']
20 changes: 20 additions & 0 deletions tests/js/roots/titles/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
Main Page
=========

This is the main page of the ``titles`` test project.

In particular, this test project is intended to demonstrate how Sphinx
can handle scoring of query matches against document titles and subsection
heading titles relative to other document matches such as terms found within
document text and object names extracted from code.

Relevance
---------

In the context of search engines, we can say that a document is **relevant**
to a user's query when it contains information that seems likely to help them
find an answer to a question they're asking, or to improve their knowledge of
the subject area they're researching.

.. automodule:: relevance
:members:
4 changes: 4 additions & 0 deletions tests/js/roots/titles/relevance.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
class Example:
"""Example class"""
num_attribute = 5
text_attribute = "string"
13 changes: 13 additions & 0 deletions tests/js/roots/titles/relevance.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Relevance
=========

In some domains, it can be straightforward to determine whether a search result
is relevant to the user's query.

For example, if we are in a software programming language domain, and a user
has issued a query for the term ``printf``, then we could consider a document
in the corpus that describes a built-in language function with the same name
as (highly) relevant. A document that only happens to mention the ``printf``
function name as part of some example code that appears on the page would
also be relevant, but likely less relevant than the one that describes the
function itself in detail.
36 changes: 35 additions & 1 deletion tests/js/searchtools.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,21 @@ describe('Basic html theme search', function() {
return req.responseText;
}

function checkRanking(expectedRanking, results) {
nextExpected = expectedRanking.pop(0);

results.forEach(result => {
let [expectedPage, expectedTitle, expectedTarget] = nextExpected;
let [page, title, target] = result;

if (page == expectedPage && title == expectedTitle && target == expectedTarget) {
nextExpected = expectedRanking.pop(0);
}
});

expect(expectedRanking.length).toEqual(0);
}

describe('terms search', function() {

it('should find "C++" when in index', function() {
Expand Down Expand Up @@ -85,7 +100,7 @@ describe('Basic html theme search', function() {
'Main Page',
'#main-page',
null,
100,
16,
'index.rst'
]
];
Expand All @@ -94,6 +109,25 @@ describe('Basic html theme search', function() {

});

describe('search result ranking', function() {

it('should score an object-name match above a page-title match', function() {
eval(loadFixture("titles/searchindex.js"));

expectedRanking = [
['index', 'relevance', '#module-relevance'], /* py:module documentation */
['relevance', 'Relevance', '#relevance'], /* main title */
['index', 'Main Page > Relevance', '#relevance'], /* subsection heading title */
];

searchParameters = Search._parseQuery('relevance');
results = Search._performSearch(...searchParameters);

checkRanking(expectedRanking, results);
});

});

});

describe("htmlToText", function() {
Expand Down