order_by: Order by value, then id. Dedup by both (#4580)

* order by value, then id. Dedup by both

* order values properly, but dedup by id only

---------

Co-authored-by: generall <andrey@vasnetsov.com>
This commit is contained in:
Luis Cossío
2024-06-29 16:38:02 -04:00
committed by GitHub
parent 291add4d37
commit eff245d840
3 changed files with 16 additions and 5 deletions

View File

@@ -319,11 +319,13 @@ impl Collection {
})
})
// Get top results
.kmerge_by(|(value_a, _), (value_b, _)| match order_by.direction() {
Direction::Asc => value_a <= value_b,
Direction::Desc => value_a >= value_b,
.kmerge_by(|(value_a, record_a), (value_b, record_b)| {
match order_by.direction() {
Direction::Asc => (value_a, record_a.id) < (value_b, record_b.id),
Direction::Desc => (value_a, record_a.id) > (value_b, record_b.id),
}
})
// Add each point only once, deduplicate point IDs
// Only keep the point with the most "valuable" order value
.dedup_by(|(_, record_a), (_, record_b)| record_a.id == record_b.id)
.map(|(_, record)| api::rest::Record::from(record))
.take(limit)

View File

@@ -195,7 +195,7 @@ async fn test_scroll_dedup() {
for point_id in result.points.iter().map(|point| point.id) {
assert!(
seen.insert(point_id),
"got point id {point_id} more than once, they should be deduplicated",
"got point id {point_id:?} more than once, they should be deduplicated",
);
}
}

View File

@@ -147,6 +147,15 @@ pub enum OrderValue {
Float(FloatPayloadType),
}
#[cfg(any(test, feature = "testing"))]
impl std::hash::Hash for OrderValue {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
match self {
OrderValue::Int(i) => i.hash(state),
OrderValue::Float(f) => f.to_bits().hash(state),
}
}
}
impl OrderValue {
const MAX: Self = Self::Float(f64::NAN);
const MIN: Self = Self::Float(f64::MIN);