Skip to content

Commit e1a4362

Browse files
committed
Included shareddoc sorting in the validate sort
1 parent 7ab4b76 commit e1a4362

File tree

2 files changed

+112
-3
lines changed

2 files changed

+112
-3
lines changed

x-pack/plugin/search-business-rules/src/main/java/org/elasticsearch/xpack/searchbusinessrules/retriever/PinnedRetrieverBuilder.java

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717
import org.elasticsearch.search.retriever.RetrieverBuilder;
1818
import org.elasticsearch.search.retriever.RetrieverBuilderWrapper;
1919
import org.elasticsearch.search.retriever.RetrieverParserContext;
20+
import org.elasticsearch.search.sort.FieldSortBuilder;
2021
import org.elasticsearch.search.sort.ScoreSortBuilder;
22+
import org.elasticsearch.search.sort.ShardDocSortField;
2123
import org.elasticsearch.search.sort.SortBuilder;
2224
import org.elasticsearch.xcontent.ConstructingObjectParser;
2325
import org.elasticsearch.xcontent.ParseField;
@@ -90,11 +92,22 @@ private void validateIdsAndDocs(List<String> ids, List<SpecifiedDocument> docs)
9092

9193
private void validateSort(SearchSourceBuilder source) {
9294
List<SortBuilder<?>> sorts = source.sorts();
93-
if (sorts != null && sorts.isEmpty() == false) {
95+
if (sorts == null || sorts.isEmpty()) {
9496
return;
9597
}
96-
if (sorts.stream().anyMatch(sort -> sort instanceof ScoreSortBuilder == false)) {
97-
throw new IllegalArgumentException("Pinned retriever only supports sorting by score. Custom sorting is not allowed.");
98+
for (SortBuilder<?> sort : sorts) {
99+
if (sort instanceof ScoreSortBuilder) {
100+
continue;
101+
}
102+
if (sort instanceof FieldSortBuilder) {
103+
FieldSortBuilder fieldSort = (FieldSortBuilder) sort;
104+
if (ShardDocSortField.NAME.equals(fieldSort.getFieldName())) {
105+
continue;
106+
}
107+
}
108+
throw new IllegalArgumentException(
109+
"Pinned retriever only supports sorting by score. Custom sorting is not allowed."
110+
);
98111
}
99112
}
100113

x-pack/plugin/search-business-rules/src/yamlRestTest/resources/rest-api-spec/test/search-business-rules/10_pinned_retriever.yml

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,9 @@ setup:
172172
- match: { hits.total.value: 5 }
173173
- match: { hits.hits.0._id: doc1 }
174174
- match: { hits.hits.1._id: doc2 }
175+
- is_true: hits.hits.0._score
176+
- is_true: hits.hits.1._score
177+
- is_true: hits.hits.0._score >= hits.hits.1._score
175178

176179
---
177180
"pinned retriever with pagination":
@@ -326,3 +329,96 @@ setup:
326329
- match: { hits.hits.2._id: doc3 }
327330
- match: { hits.hits.3._id: doc4 }
328331
- match: { hits.hits.4._id: doc5 }
332+
333+
---
334+
"pinned retriever error case - both ids and docs":
335+
- do:
336+
# Expect a bad_request error with this message
337+
catch: /Both 'ids' and 'docs' cannot be specified at the same time/
338+
search:
339+
index: test-index1
340+
body:
341+
retriever:
342+
pinned:
343+
ids: ["doc1"] # Provide some IDs
344+
docs: # Provide some docs
345+
- _index: test-index1
346+
_id: doc2
347+
retriever:
348+
standard:
349+
query:
350+
match_all: {}
351+
352+
---
353+
"pinned retriever error case - invalid sort":
354+
- do:
355+
# Expect the earlier validation error
356+
catch: /cannot specify \[retriever\] and \[sort\]/
357+
search:
358+
index: test-index1
359+
body:
360+
sort: [ "text" ]
361+
retriever:
362+
pinned:
363+
ids: ["doc1"]
364+
retriever:
365+
standard:
366+
query:
367+
match_all: {}
368+
369+
---
370+
"pinned retriever error case - duplicate id":
371+
- do:
372+
# Catch duplicate ID error
373+
catch: /duplicate id found/
374+
search:
375+
index: test-index1
376+
body:
377+
retriever:
378+
pinned:
379+
ids: ["doc1", "doc1"]
380+
retriever:
381+
standard:
382+
query:
383+
match_all: {}
384+
385+
---
386+
"pinned retriever with empty docs array":
387+
- do:
388+
search:
389+
index: test-index1
390+
body:
391+
retriever:
392+
pinned:
393+
docs: [] # Empty docs array
394+
retriever:
395+
standard:
396+
query:
397+
match_all: {}
398+
# Expect regular match_all results, no pinning effect
399+
- match: { hits.total.value: 5 }
400+
- match: { hits.hits.0._id: doc1 }
401+
- match: { hits.hits.1._id: doc2 }
402+
- match: { hits.hits.2._id: doc3 }
403+
- match: { hits.hits.3._id: doc4 }
404+
- match: { hits.hits.4._id: doc5 }
405+
406+
---
407+
"pinned retriever with ids and empty docs array":
408+
- do:
409+
search:
410+
index: test-index1
411+
body:
412+
retriever:
413+
pinned:
414+
ids: ["doc1"] # Provide IDs
415+
docs: [] # Provide empty docs array
416+
retriever:
417+
standard:
418+
query:
419+
match_all: {}
420+
# Expect pinning based on "ids", empty "docs" is ignored
421+
- match: { hits.total.value: 5 }
422+
- match: { hits.hits.0._id: doc1 } # doc1 should be pinned
423+
- match: { hits.hits.1._id: doc2 } # Rest follow
424+
- match: { hits.hits.2._id: doc3 }

0 commit comments

Comments
 (0)