Skip to content

Commit 3dc51df

Browse files
Add undocumented rank option to elasticsearch_dsl.search.Search (#1692) (#1694)
(cherry picked from commit 5422cf0) Co-authored-by: Miguel Grinberg <[email protected]>
1 parent 63fd20d commit 3dc51df

File tree

2 files changed

+41
-1
lines changed

2 files changed

+41
-1
lines changed

elasticsearch_dsl/search.py

+29-1
Original file line numberDiff line numberDiff line change
@@ -318,8 +318,9 @@ def __init__(self, **kwargs):
318318

319319
self.aggs = AggsProxy(self)
320320
self._sort = []
321-
self._collapse = {}
322321
self._knn = []
322+
self._rank = {}
323+
self._collapse = {}
323324
self._source = None
324325
self._highlight = {}
325326
self._highlight_opts = {}
@@ -408,6 +409,7 @@ def _clone(self):
408409

409410
s._response_class = self._response_class
410411
s._knn = [knn.copy() for knn in self._knn]
412+
s._rank = self._rank.copy()
411413
s._collapse = self._collapse.copy()
412414
s._sort = self._sort[:]
413415
s._source = copy.copy(self._source) if self._source is not None else None
@@ -451,6 +453,8 @@ def update_from_dict(self, d):
451453
self._knn = d.pop("knn")
452454
if isinstance(self._knn, dict):
453455
self._knn = [self._knn]
456+
if "rank" in d:
457+
self._rank = d.pop("rank")
454458
if "collapse" in d:
455459
self._collapse = d.pop("collapse")
456460
if "sort" in d:
@@ -558,6 +562,27 @@ def knn(
558562
s._knn[-1]["similarity"] = similarity
559563
return s
560564

565+
def rank(self, rrf=None):
566+
"""
567+
Defines a method for combining and ranking results sets from a combination
568+
of searches. Requires a minimum of 2 results sets.
569+
570+
:arg rrf: Set to ``True`` or an options dictionary to set the rank method to reciprocal rank fusion (RRF).
571+
572+
Example::
573+
s = Search()
574+
s = s.query('match', content='search text')
575+
s = s.knn(field='embedding', k=5, num_candidates=10, query_vector=vector)
576+
s = s.rank(rrf=True)
577+
578+
Note: This option is in technical preview and may change in the future. The syntax will likely change before GA.
579+
"""
580+
s = self._clone()
581+
s._rank = {}
582+
if rrf is not None and rrf is not False:
583+
s._rank["rrf"] = {} if rrf is True else rrf
584+
return s
585+
561586
def source(self, fields=None, **kwargs):
562587
"""
563588
Selectively control how the _source field is returned.
@@ -747,6 +772,9 @@ def to_dict(self, count=False, **kwargs):
747772
else:
748773
d["knn"] = self._knn
749774

775+
if self._rank:
776+
d["rank"] = self._rank
777+
750778
# count request doesn't care for sorting and other things
751779
if not count:
752780
if self.post_filter:

tests/test_search.py

+12
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,18 @@ def test_knn():
288288
} == s.to_dict()
289289

290290

291+
def test_rank():
292+
s = search.Search()
293+
s.rank(rrf=False)
294+
assert {} == s.to_dict()
295+
296+
s = s.rank(rrf=True)
297+
assert {"rank": {"rrf": {}}} == s.to_dict()
298+
299+
s = s.rank(rrf={"window_size": 50, "rank_constant": 20})
300+
assert {"rank": {"rrf": {"window_size": 50, "rank_constant": 20}}} == s.to_dict()
301+
302+
291303
def test_sort():
292304
s = search.Search()
293305
s = s.sort("fielda", "-fieldb")

0 commit comments

Comments
 (0)