Skip to content

Commit 505be8c

Browse files
authored
Search: custom search page ranking (#7237)
* Add search page rankings * Update docs * Fix tests * Fix linter * Update docs * Pass dict, config object isn't serializable * Do ranking at query time * Update docs * Linter * Add tip * Add comment * TODO about alternative precedence
1 parent 0e7b698 commit 505be8c

File tree

16 files changed

+570
-34
lines changed

16 files changed

+570
-34
lines changed

docs/config-file/v2.rst

+87-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ Below is an example YAML file which shows the most common configuration options:
2525
# configuration: mkdocs.yml
2626
2727
# Optionally build your docs in additional formats such as PDF
28-
formats:
28+
formats:
2929
- pdf
3030
3131
# Optionally set the version of Python and requirements required to build your docs
@@ -74,11 +74,15 @@ Example:
7474

7575
.. code-block:: yaml
7676
77+
version: 2
78+
7779
# Default
7880
formats: []
7981
8082
.. code-block:: yaml
8183
84+
version: 2
85+
8286
# Build PDF & ePub
8387
formats:
8488
- epub
@@ -90,6 +94,8 @@ Example:
9094

9195
.. code-block:: yaml
9296
97+
version: 2
98+
9399
# Build all formats
94100
formats: all
95101
@@ -104,6 +110,8 @@ Configuration of the Python environment to be used.
104110

105111
.. code-block:: yaml
106112
113+
version: 2
114+
107115
python:
108116
version: 3.7
109117
install:
@@ -153,6 +161,8 @@ Example:
153161

154162
.. code-block:: yaml
155163
164+
version: 2
165+
156166
python:
157167
version: 3.7
158168
install:
@@ -199,6 +209,8 @@ Example:
199209

200210
.. code-block:: yaml
201211
212+
version: 2
213+
202214
python:
203215
version: 3.7
204216
install:
@@ -242,6 +254,8 @@ Configuration for Conda support.
242254

243255
.. code-block:: yaml
244256
257+
version: 2
258+
245259
conda:
246260
environment: environment.yml
247261
@@ -260,6 +274,8 @@ Configuration for the documentation build process.
260274

261275
.. code-block:: yaml
262276
277+
version: 2
278+
263279
build:
264280
image: latest
265281
@@ -290,6 +306,8 @@ Configuration for Sphinx documentation
290306

291307
.. code-block:: yaml
292308
309+
version: 2
310+
293311
sphinx:
294312
builder: html
295313
configuration: conf.py
@@ -335,6 +353,8 @@ Configuration for Mkdocs documentation.
335353

336354
.. code-block:: yaml
337355
356+
version: 2
357+
338358
mkdocs:
339359
configuration: mkdocs.yml
340360
fail_on_warning: false
@@ -374,6 +394,8 @@ VCS submodules configuration.
374394

375395
.. code-block:: yaml
376396
397+
version: 2
398+
377399
submodules:
378400
include:
379401
- one
@@ -394,6 +416,8 @@ List of submodules to be included.
394416

395417
.. code-block:: yaml
396418
419+
version: 2
420+
397421
submodules:
398422
include: all
399423
@@ -412,6 +436,8 @@ List of submodules to be excluded.
412436

413437
.. code-block:: yaml
414438
439+
version: 2
440+
415441
submodules:
416442
exclude: all
417443
@@ -427,6 +453,65 @@ Do a recursive clone of the submodules.
427453

428454
This is ignored if there aren't submodules to clone.
429455

456+
search
457+
~~~~~~
458+
459+
Settings for more control over :doc:`/server-side-search`.
460+
461+
.. code-block:: yaml
462+
463+
version: 2
464+
465+
search:
466+
ranking:
467+
api/v1/*: -1
468+
api/v2/*: 4
469+
470+
search.ranking
471+
``````````````
472+
473+
Set a custom search rank over pages matching a pattern.
474+
475+
:Type: ``map`` of patterns to ranks
476+
:Default: ``{}``
477+
478+
Patterns are matched against the final html pages produced by the build
479+
(you should try to match `index.html`, not `docs/index.rst`).
480+
Patterns can include some special characters:
481+
482+
- ``*`` matches everything
483+
- ``?`` matches any single character
484+
- ``[seq]`` matches any character in ``seq``
485+
486+
The rank can be an integer number between -10 and 10 (inclusive).
487+
Pages with a rank closer to -10 will appear further down the list of results,
488+
and pages with a rank closer to 10 will appear higher in the list of results.
489+
Note that 0 means *normal rank*, not *no rank*.
490+
491+
.. code-block:: yaml
492+
493+
version: 2
494+
495+
search:
496+
ranking:
497+
# Match a single file
498+
tutorial.hml: 2
499+
500+
# Match all files under the api/v1 directory
501+
api/v1/*: -5
502+
503+
# Match all files that end with tutorial.html
504+
*/tutorial.html: 3
505+
506+
.. note::
507+
508+
The final rank will be the last pattern to match the page.
509+
510+
.. tip::
511+
512+
Is better to decrease the rank of pages you want to deprecate,
513+
rather than increasing the rank of the other pages.
514+
430515
Schema
431516
------
432517

@@ -468,6 +553,7 @@ New settings
468553
- :ref:`config-file/v2:mkdocs`
469554
- :ref:`config-file/v2:submodules`
470555
- :ref:`config-file/v2:python.install`
556+
- :ref:`config-file/v2:search`
471557

472558
Migrating from the web interface
473559
--------------------------------

docs/guides/searching-with-readthedocs.rst

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ Searching with Read the Docs
22
============================
33

44
Read the Docs uses :doc:`/server-side-search` to power our search.
5-
This guide explains how to add a "search as you type" feature to your documentation,
5+
This guide explains how to add a "search as you type" feature to your documentation,
66
and how to use advanced query syntax to get more accurate results.
77

88
You can find information on the search architecture and how we index documents in our
@@ -20,7 +20,7 @@ Enable "search as you type" in your documentation
2020
documentation more closely with the search implementation of Read the Docs.
2121
It adds a clean and minimal full-page search UI that supports a **search as you type** feature.
2222

23-
To try this feature,
23+
To try this feature,
2424
you can press :guilabel:`/` (forward slash) and start typing or just visit these URLs:
2525

2626
- https://docs.readthedocs.io/?rtd_search=contributing

docs/server-side-search.rst

+8-3
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,12 @@ Search results land on the exact content you were looking for
2525
We index every heading in the document,
2626
allowing you to get search results exactly to the content that you are searching for.
2727
Try this out by searching for `"full-text search"`_.
28-
28+
29+
Full control over which results should be listed first
30+
Set a custom rank per page,
31+
allowing you to deprecate content, and always show relevant content to your users first.
32+
See :ref:`config-file/v2:search.ranking`.
33+
2934
Search across projects you have access to (|com_brand|)
3035
This allows you to search across all the projects you access to in your Dashboard.
3136
**Don't remember where you found that document the other day?
@@ -35,10 +40,10 @@ Special query syntax for more specific results.
3540
We support a full range of search queries.
3641
You can see some examples in our :ref:`guides/searching-with-readthedocs:search query syntax` guide.
3742

38-
..
43+
..
3944
Code object searching
4045
With the user of :doc:`Sphinx Domains <sphinx:/usage/restructuredtext/domains>` we are able to automatically provide direct search results to your Code objects.
41-
You can try this out with our docs here by searching for
46+
You can try this out with our docs here by searching for
4247
TODO: Find good examples in our docs, API maybe?
4348
4449
.. _"full-text search": https://docs.readthedocs.io/en/latest/search.html?q=%22full-text+search%22

readthedocs/config/config.py

+41-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
from django.conf import settings
1111

1212
from readthedocs.config.utils import list_to_dict, to_dict
13-
from readthedocs.projects.constants import DOCUMENTATION_CHOICES
1413

1514
from .find import find_one
1615
from .models import (
@@ -20,6 +19,7 @@
2019
Python,
2120
PythonInstall,
2221
PythonInstallRequirements,
22+
Search,
2323
Sphinx,
2424
Submodules,
2525
)
@@ -32,6 +32,7 @@
3232
validate_dict,
3333
validate_list,
3434
validate_path,
35+
validate_path_pattern,
3536
validate_string,
3637
)
3738

@@ -155,6 +156,7 @@ class BuildConfigBase:
155156
'sphinx',
156157
'mkdocs',
157158
'submodules',
159+
'search',
158160
]
159161

160162
default_build_image = settings.DOCKER_DEFAULT_VERSION
@@ -652,6 +654,10 @@ def submodules(self):
652654
recursive=True,
653655
)
654656

657+
@property
658+
def search(self):
659+
return Search(ranking={})
660+
655661

656662
class BuildConfigV2(BuildConfigBase):
657663

@@ -666,7 +672,6 @@ class BuildConfigV2(BuildConfigBase):
666672
'dirhtml': 'sphinx_htmldir',
667673
'singlehtml': 'sphinx_singlehtml',
668674
}
669-
builders_display = dict(DOCUMENTATION_CHOICES)
670675

671676
def validate(self):
672677
"""
@@ -686,6 +691,7 @@ def validate(self):
686691
self._config['mkdocs'] = self.validate_mkdocs()
687692
self._config['sphinx'] = self.validate_sphinx()
688693
self._config['submodules'] = self.validate_submodules()
694+
self._config['search'] = self.validate_search()
689695
self.validate_keys()
690696

691697
def validate_formats(self):
@@ -1013,6 +1019,35 @@ def validate_submodules(self):
10131019

10141020
return submodules
10151021

1022+
def validate_search(self):
1023+
"""
1024+
Validates the search key.
1025+
1026+
- Ranking is a map of path patterns to a rank.
1027+
- The path pattern supports basic globs (*, ?, [seq]).
1028+
- The rank can be a integer number between -10 and 10.
1029+
"""
1030+
raw_search = self._raw_config.get('search', {})
1031+
with self.catch_validation_error('search'):
1032+
validate_dict(raw_search)
1033+
1034+
search = {}
1035+
with self.catch_validation_error('search.ranking'):
1036+
ranking = self.pop_config('search.ranking', {})
1037+
validate_dict(ranking)
1038+
1039+
valid_rank_range = list(range(-10, 10 + 1))
1040+
1041+
final_ranking = {}
1042+
for pattern, rank in ranking.items():
1043+
pattern = validate_path_pattern(pattern)
1044+
validate_choice(rank, valid_rank_range)
1045+
final_ranking[pattern] = rank
1046+
1047+
search['ranking'] = final_ranking
1048+
1049+
return search
1050+
10161051
def validate_keys(self):
10171052
"""
10181053
Checks that we don't have extra keys (invalid ones).
@@ -1107,6 +1142,10 @@ def doctype(self):
11071142
def submodules(self):
11081143
return Submodules(**self._config['submodules'])
11091144

1145+
@property
1146+
def search(self):
1147+
return Search(**self._config['search'])
1148+
11101149

11111150
def load(path, env_config):
11121151
"""

readthedocs/config/models.py

+5
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,8 @@ class Mkdocs(Base):
6868
class Submodules(Base):
6969

7070
__slots__ = ('include', 'exclude', 'recursive')
71+
72+
73+
class Search(Base):
74+
75+
__slots__ = ('ranking',)

0 commit comments

Comments
 (0)