Skip to content

Commit d078a09

Browse files
committed
Allowed low ranking search results to be returned in doc search.
This also indicates to the user that they can use the PostgreSQL websearch_to_tsquery syntax.
1 parent 418d589 commit d078a09

File tree

4 files changed

+40
-17
lines changed

4 files changed

+40
-17
lines changed

djangoproject/scss/_style.scss

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2763,7 +2763,7 @@ form {
27632763
display: block;
27642764
font-weight: 400;
27652765
height: 30px;
2766-
margin: 10px 0px;
2766+
margin: 10px 0px 5px;
27672767
padding: 6px 14% 8px 10px;
27682768
text-indent: 0;
27692769
vertical-align: middle;
@@ -2925,7 +2925,13 @@ form {
29252925
margin: 0 0 10px 0;
29262926

29272927
button {
2928-
top: 19%;
2928+
top: 13%;
2929+
}
2930+
2931+
.helptext {
2932+
font-size: 1.1rem;
2933+
line-height: 1.5rem;
2934+
display: block;
29292935
}
29302936
}
29312937
}

docs/models.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import html
33
import json
44
import operator
5+
import re
56
from functools import reduce
67
from pathlib import Path
78

@@ -251,6 +252,13 @@ def search(self, query_text, release):
251252
)
252253
search_rank = SearchRank(models.F("search"), search_query)
253254
similarity = TrigramSimilarity("title", query_text)
255+
search_filter = Q(rank__gt=0.3)
256+
# Check if query_text contains PostgreSQL websearch_to_tsquery syntax.
257+
# Specifically, phrases in double quotes or negation using -.
258+
if bool(re.search(r'"[^"]+"| -\w+', query_text)):
259+
# Filter by search_query only. This returns an accurate result set not
260+
# impacted by "fuzzy" search additions.
261+
search_filter = Q(search=search_query)
254262
return (
255263
self.prefetch_related(
256264
Prefetch(
@@ -261,12 +269,9 @@ def search(self, query_text, release):
261269
"release__release", queryset=Release.objects.only("version")
262270
),
263271
)
264-
.filter(
265-
release_id=release.id,
266-
search=search_query,
267-
)
272+
.alias(rank=search_rank + similarity)
273+
.filter(Q(release_id=release.id) & search_filter)
268274
.annotate(
269-
rank=search_rank + similarity,
270275
headline=SearchHeadline(
271276
"title",
272277
search_query,

docs/templates/docs/search_form.html

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,9 @@
88
<i class="icon icon-search"></i>
99
<span class="visuallyhidden">{% trans 'Search' %}</span>
1010
</button>
11+
<span class="helptext quiet">
12+
{% blocktranslate trimmed %}
13+
Uses PostgreSQL <code>websearch_to_tsquery</code> syntax e.g. use "quoted text" for a phrase.
14+
{% endblocktranslate %}
15+
</span>
1116
</form>

docs/tests.py

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -548,18 +548,16 @@ def setUp(self):
548548
def test_search(self):
549549
expected_list = [
550550
(
551-
0.96982837,
552551
"releases/1.2.1",
553-
"<mark>Django</mark> 1.2.1 release notes",
552+
"<mark>Django</mark> 1.2.1 release notes", # Ranked: 0.96982837.
554553
(
555554
"<mark>Django</mark> 1.2.1 release notes ¶ \n "
556555
"<mark>Django</mark> 1.2.1 was released almost immediately after 1.2.0 to correct two small"
557556
),
558557
),
559558
(
560-
0.9490876,
561559
"releases/1.9.4",
562-
"<mark>Django</mark> 1.9.4 release notes",
560+
"<mark>Django</mark> 1.9.4 release notes", # Ranked: 0.9490876.
563561
(
564562
"<mark>Django</mark> 1.9.4 release notes ¶ \n "
565563
"March 5, 2016 \n "
@@ -570,24 +568,24 @@ def test_search(self):
570568
self.assertQuerySetEqual(
571569
Document.objects.search("django", self.release),
572570
expected_list,
573-
transform=attrgetter("rank", "path", "headline", "highlight"),
571+
transform=attrgetter("path", "headline", "highlight"),
574572
)
575573

576574
def test_websearch(self):
577575
self.assertQuerySetEqual(
578576
Document.objects.search('django "release notes" -packaging', self.release),
579-
[("Django 1.9.4 release notes", 1.5675676)],
580-
transform=attrgetter("title", "rank"),
577+
["Django 1.9.4 release notes"],
578+
transform=attrgetter("title"),
581579
)
582580

583581
def test_multilingual_search(self):
584582
self.assertQuerySetEqual(
585583
Document.objects.search("publication", self.release_fr),
586584
[
587-
("Notes de publication de Django 1.2.1", 1.0693262),
588-
("Notes de publication de Django 1.9.4", 1.0458658),
585+
"Notes de publication de Django 1.2.1", # Ranked: 1.0693262.
586+
"Notes de publication de Django 1.9.4", # Ranked: 1.0458658.
589587
],
590-
transform=attrgetter("title", "rank"),
588+
transform=attrgetter("title"),
591589
)
592590

593591
def test_empty_search(self):
@@ -642,6 +640,15 @@ def test_search_highlight_stemmed(self):
642640
transform=attrgetter("headline", "highlight"),
643641
)
644642

643+
def test_search_title(self):
644+
misspelled_query = Document.objects.search("viewss", self.release)
645+
with self.assertNumQueries(2):
646+
self.assertQuerySetEqual(
647+
misspelled_query,
648+
["Generic views"],
649+
transform=attrgetter("headline"),
650+
)
651+
645652

646653
class TemplateTestCase(TestCase):
647654
def _assertOGTitleEqual(self, doc, expected):

0 commit comments

Comments
 (0)