use crate::segment::payload_json;
use crate::segment::types::{Payload, PointIdType};
use crate::shard::operations::CollectionUpdateOperations;
use crate::shard::operations::payload_ops::{PayloadOps, SetPayloadOp};
use crate::shard::operations::point_ops::{PointOperations, PointStructPersisted, VectorStructPersisted};
use super::UpdateBatchPlan;
fn point_id(id: u64) -> PointIdType {
PointIdType::NumId(id)
}
fn upsert(id: u64, payload: Payload) -> CollectionUpdateOperations {
CollectionUpdateOperations::PointOperation(PointOperations::UpsertPoints(
vec![PointStructPersisted {
id: point_id(id),
vector: VectorStructPersisted::Single(vec![1.0, 0.0]),
payload: Some(payload),
}]
.into(),
))
}
fn set_payload(id: u64, payload: Payload) -> CollectionUpdateOperations {
CollectionUpdateOperations::PayloadOperation(PayloadOps::SetPayload(SetPayloadOp {
payload,
points: Some(vec![point_id(id)]),
filter: None,
key: None,
}))
}
fn delete(id: u64) -> CollectionUpdateOperations {
CollectionUpdateOperations::PointOperation(PointOperations::DeletePoints {
ids: vec![point_id(id)],
})
}
#[test]
fn folds_operations_on_the_same_point() {
let plan = UpdateBatchPlan::build([
(1, upsert(7, payload_json! { "a": 1 })),
(2, set_payload(7, payload_json! { "b": 2 })),
])
.unwrap();
assert_eq!(plan.len(), 1);
assert_eq!(plan.point_ids_needing_stored_point().count(), 0);
let (id, updates) = plan.into_point_updates().next().unwrap();
assert_eq!(id, point_id(7));
assert_eq!(updates.version(), 2);
let point = updates.materialize(id, None).unwrap().unwrap();
assert_eq!(point.version, 2);
assert_eq!(point.payload, payload_json! { "a": 1, "b": 2 });
}
#[test]
fn modification_only_batch_needs_the_stored_point() {
let plan = UpdateBatchPlan::build([(1, set_payload(7, payload_json! { "b": 2 }))]).unwrap();
assert_eq!(
plan.point_ids_needing_stored_point().collect::<Vec<_>>(),
vec![point_id(7)],
);
}
#[test]
fn delete_discards_preceding_operations() {
let plan = UpdateBatchPlan::build([
(1, set_payload(7, payload_json! { "b": 2 })),
(2, delete(7)),
])
.unwrap();
assert_eq!(plan.point_ids_needing_stored_point().count(), 0);
let (id, updates) = plan.into_point_updates().next().unwrap();
assert!(updates.materialize(id, None).unwrap().is_none());
}
#[test]
fn upsert_after_delete_recreates_the_point() {
let plan =
UpdateBatchPlan::build([(1, delete(7)), (2, upsert(7, payload_json! { "a": 1 }))]).unwrap();
let (id, updates) = plan.into_point_updates().next().unwrap();
let point = updates.materialize(id, None).unwrap().unwrap();
assert_eq!(point.payload, payload_json! { "a": 1 });
}
#[test]
fn rejects_filter_selected_operations() {
let operation =
CollectionUpdateOperations::PayloadOperation(PayloadOps::SetPayload(SetPayloadOp {
payload: payload_json! { "a": 1 },
points: None,
filter: Some(Default::default()),
key: None,
}));
assert!(UpdateBatchPlan::build([(1, operation)]).is_err());
}