Fix the pagination bug

where the last document of the previous page was duplicated as the first
document of the current page. This was due to a bug on the custom nth
function of the sort ranking rule skipping `n-1` documents instead of `n`
This commit is contained in:
ManyTheFish
2025-11-18 14:30:35 +01:00
committed by Louis Dureuil
parent 97e6ae1957
commit 62065ed30d
2 changed files with 96 additions and 1 deletions

View File

@@ -1339,3 +1339,98 @@ async fn get_document_with_vectors() {
}
"###);
}
#[actix_rt::test]
async fn test_fetch_documents_pagination_with_sorting() {
let server = Server::new_shared();
let index = server.unique_index();
let (task, _code) = index.create(None).await;
server.wait_task(task.uid()).await.succeeded();
// Add documents as described in the bug report
let documents = json!([
{"id": 1, "name": "a"},
{"id": 2, "name": "b"},
{"id": 3, "name": "c"},
{"id": 4, "name": "d"},
{"id": 5, "name": "e"},
{"id": 6, "name": "f"}
]);
let (task, code) = index.add_documents(documents, None).await;
assert_eq!(code, 202);
server.wait_task(task.uid()).await.succeeded();
// Set name as sortable attribute
let (task, code) = index.update_settings_sortable_attributes(json!(["name"])).await;
assert_eq!(code, 202);
server.wait_task(task.uid()).await.succeeded();
// Request 1 (first page): offset 0, limit 2
let (response, code) = index
.fetch_documents(json!({
"offset": 0,
"limit": 2,
"sort": ["name:asc"]
}))
.await;
assert_eq!(code, 200);
let results = response["results"].as_array().unwrap();
snapshot!(json_string!(results), @r#"
[
{
"id": 1,
"name": "a"
},
{
"id": 2,
"name": "b"
}
]
"#);
// Request 2 (second page): offset 2, limit 2
let (response, code) = index
.fetch_documents(json!({
"offset": 2,
"limit": 2,
"sort": ["name:asc"]
}))
.await;
assert_eq!(code, 200);
let results = response["results"].as_array().unwrap();
snapshot!(json_string!(results), @r###"
[
{
"id": 3,
"name": "c"
},
{
"id": 4,
"name": "d"
}
]
"###);
// Request 3 (third page): offset 4, limit 2
let (response, code) = index
.fetch_documents(json!({
"offset": 4,
"limit": 2,
"sort": ["name:asc"]
}))
.await;
assert_eq!(code, 200);
let results = response["results"].as_array().unwrap();
snapshot!(json_string!(results), @r#"
[
{
"id": 5,
"name": "e"
},
{
"id": 6,
"name": "f"
}
]
"#);
}

View File

@@ -87,7 +87,7 @@ impl Iterator for SortedDocumentsIterator<'_> {
};
// Otherwise don't directly iterate over children, skip them if we know we will go further
let mut to_skip = n - 1;
let mut to_skip = n;
while to_skip > 0 {
if let Err(e) = SortedDocumentsIterator::update_current(
current_child,