#[non_exhaustive]pub enum SnapshotMutation {
Upsert {
point: Point,
},
DeleteIds {
ids: Vec<PointId>,
},
DeleteFilter {
filter: Filter,
},
}Expand description
One operation in an ordered immutable-root mutation batch.
Variants (Non-exhaustive)§
This enum is marked as non-exhaustive
Non-exhaustive enums could have additional variants added in future. Therefore, when matching against variants of non-exhaustive enums, an extra wildcard arm must be added to account for any future variants.
Upsert
Adds a new point or replaces an existing point with the same typed ID.
DeleteIds
Deletes the supplied typed IDs.
DeleteFilter
Deletes every point matching a filter.
Implementations§
Source§impl SnapshotMutation
impl SnapshotMutation
Sourcepub fn delete_ids(ids: impl IntoIterator<Item = PointId>) -> Self
pub fn delete_ids(ids: impl IntoIterator<Item = PointId>) -> Self
Creates a typed-ID deletion mutation.
Examples found in repository?
examples/lancedb_git_vdb_profile.rs (lines 118-120)
79fn mutate(
80 input: &Path,
81 repository: &Path,
82 build_report: &Path,
83 fraction: f64,
84 output: &Path,
85 sample_stable: bool,
86) -> Result<(), Box<dyn std::error::Error>> {
87 let spec = read_spec(input)?;
88 if !(0.0..=1.0).contains(&fraction) || fraction == 0.0 {
89 return Err("mutation fraction must be greater than zero and at most one".into());
90 }
91 let vectors = read_vectors(&spec.points_path, spec.point_count, spec.dimension)?;
92 let points = make_points(&vectors);
93 let count = ((spec.point_count as f64 * fraction).round() as usize).clamp(1, spec.point_count);
94 let mut changed = if sample_stable {
95 sample_stable_points(points, count)?
96 } else {
97 points[..count].to_vec()
98 };
99 for point in &mut changed {
100 point.vector[0] += 0.001;
101 }
102 let build: serde_json::Value = serde_json::from_slice(&fs::read(build_report)?)?;
103 let root = build
104 .get("root")
105 .and_then(serde_json::Value::as_str)
106 .ok_or("build report root is missing")?;
107 let engine = SnapshotEngine::open(repository)?;
108
109 let upsert_started = Instant::now();
110 let upserted = engine.apply(
111 root,
112 changed.into_iter().map(SnapshotMutation::upsert).collect(),
113 )?;
114 let upsert_us = micros(upsert_started);
115 let delete_started = Instant::now();
116 let deleted = engine.apply(
117 root,
118 vec![SnapshotMutation::delete_ids(
119 (0..count).map(|id| PointId::from(id as u64)),
120 )],
121 )?;
122 let delete_us = micros(delete_started);
123 fs::write(
124 output,
125 serde_json::to_vec_pretty(&json!({
126 "schema_version": 1,
127 "root": root,
128 "fraction": fraction,
129 "points": count,
130 "sample_stable": sample_stable,
131 "upsert_us": upsert_us,
132 "delete_us": delete_us,
133 "upsert_root": upserted.root(),
134 "delete_root": deleted.root(),
135 "on_disk_bytes_after": directory_bytes(repository)?,
136 }))?,
137 )?;
138 Ok(())
139}More examples
examples/lancedb_git_vdb_runner.rs (lines 111-113)
28fn main() -> Result<(), Box<dyn std::error::Error>> {
29 let mut args = env::args_os().skip(1);
30 let input = args.next().ok_or("usage: runner INPUT.json OUTPUT.json")?;
31 let output = args.next().ok_or("usage: runner INPUT.json OUTPUT.json")?;
32 if args.next().is_some() {
33 return Err("usage: runner INPUT.json OUTPUT.json".into());
34 }
35 let spec: RunSpec = serde_json::from_slice(&fs::read(input)?)?;
36 if spec.schema_version != 1 {
37 return Err(format!("unsupported harness schema version {}", spec.schema_version).into());
38 }
39 let vectors = read_vectors(&spec.points_path, spec.point_count, spec.dimension)?;
40 let queries = read_vectors(&spec.queries_path, spec.query_count, spec.dimension)?;
41 let points = make_points(&vectors);
42 let maximum_k = *spec.k.iter().max().ok_or("k must not be empty")?;
43 let config = CollectionConfig {
44 dimension: spec.dimension,
45 ..CollectionConfig::default()
46 };
47
48 let setup_started = Instant::now();
49 let core_dir = tempfile::TempDir::new()?;
50 let engine = SnapshotEngine::init(core_dir.path())?;
51 let setup_us = micros(setup_started);
52 let build_started = Instant::now();
53 let snapshot = engine.build(config.clone(), points.clone())?;
54 let build_us = micros(build_started);
55 let baseline_on_disk_bytes = directory_bytes(core_dir.path())?;
56
57 let (exact_query_us, exact_results, exact_vectors_scored) =
58 query_all(&snapshot, &queries, maximum_k, true, None)?;
59 let (approximate_query_us, approximate_results, approximate_vectors_scored) =
60 query_all(&snapshot, &queries, maximum_k, false, None)?;
61 let snapshot_throughput = json!({
62 "exact": query_snapshot_throughput(
63 &snapshot,
64 &queries,
65 maximum_k,
66 true,
67 &spec.concurrency,
68 )?,
69 "approximate": query_snapshot_throughput(
70 &snapshot,
71 &queries,
72 maximum_k,
73 false,
74 &spec.concurrency,
75 )?,
76 });
77
78 let mut filtered = Map::new();
79 for selectivity in &spec.filter_selectivities {
80 let filter = selectivity_filter(*selectivity);
81 let (exact_us, exact, exact_scored) =
82 query_all(&snapshot, &queries, maximum_k, true, Some(filter.clone()))?;
83 let (approximate_us, approximate, approximate_scored) =
84 query_all(&snapshot, &queries, maximum_k, false, Some(filter))?;
85 filtered.insert(
86 selectivity.to_string(),
87 json!({
88 "exact_query_us": exact_us,
89 "approximate_query_us": approximate_us,
90 "exact_results": exact,
91 "approximate_results": approximate,
92 "exact_vectors_scored": exact_scored,
93 "approximate_vectors_scored": approximate_scored,
94 }),
95 );
96 }
97
98 let mut mutations = Map::new();
99 for fraction in &spec.mutation_fractions {
100 let count = fraction_count(spec.point_count, *fraction);
101 let changed = changed_points(&points[..count]);
102 let upsert_started = Instant::now();
103 let upserted = engine.apply(
104 snapshot.root(),
105 changed.into_iter().map(SnapshotMutation::upsert).collect(),
106 )?;
107 let upsert_us = micros(upsert_started);
108 let delete_started = Instant::now();
109 let deleted = engine.apply(
110 snapshot.root(),
111 vec![SnapshotMutation::delete_ids(
112 (0..count).map(|id| PointId::from(id as u64)),
113 )],
114 )?;
115 let delete_us = micros(delete_started);
116 mutations.insert(
117 fraction.to_string(),
118 json!({
119 "points": count,
120 "upsert_us": upsert_us,
121 "delete_us": delete_us,
122 "upsert_root": upserted.root(),
123 "delete_root": deleted.root(),
124 }),
125 );
126 }
127
128 let adapter_setup_started = Instant::now();
129 let adapter_dir = tempfile::TempDir::new()?;
130 let database = Database::init_bare(adapter_dir.path())?;
131 let collection = database.create_collection("benchmark", config)?;
132 let adapter_setup_us = micros(adapter_setup_started);
133 let adapter_build_started = Instant::now();
134 let adapter_root = collection.upsert(points)?.root;
135 let adapter_build_us = micros(adapter_build_started);
136 if adapter_root != snapshot.root() {
137 return Err("snapshot-core and named-adapter roots differ".into());
138 }
139 query_collection_all(&collection, &queries[..1], maximum_k, true, None)?;
140 query_collection_all(&collection, &queries[..1], maximum_k, false, None)?;
141 let (adapter_exact_query_us, adapter_exact_results, adapter_exact_vectors_scored) =
142 query_collection_all(&collection, &queries, maximum_k, true, None)?;
143 let (
144 adapter_approximate_query_us,
145 adapter_approximate_results,
146 adapter_approximate_vectors_scored,
147 ) = query_collection_all(&collection, &queries, maximum_k, false, None)?;
148 let adapter_throughput = json!({
149 "exact": query_collection_throughput(
150 &collection,
151 &queries,
152 maximum_k,
153 true,
154 &spec.concurrency,
155 )?,
156 "approximate": query_collection_throughput(
157 &collection,
158 &queries,
159 maximum_k,
160 false,
161 &spec.concurrency,
162 )?,
163 });
164 let historical_started = Instant::now();
165 let historical = collection.at(&adapter_root)?;
166 let historical_count = historical.count(None)?.count;
167 let historical_read_us = micros(historical_started);
168
169 let report = json!({
170 "schema_version": 1,
171 "engine": "git-vdb",
172 "case_name": spec.case_name,
173 "point_count": spec.point_count,
174 "dimension": spec.dimension,
175 "query_count": spec.query_count,
176 "k": spec.k,
177 "root": snapshot.root(),
178 "setup_us": setup_us,
179 "snapshot_core": {
180 "build_us": build_us,
181 "exact_query_us": exact_query_us,
182 "approximate_query_us": approximate_query_us,
183 "exact_results": exact_results,
184 "approximate_results": approximate_results,
185 "exact_vectors_scored": exact_vectors_scored,
186 "approximate_vectors_scored": approximate_vectors_scored,
187 "throughput": snapshot_throughput,
188 "filtered": filtered,
189 "mutations": mutations,
190 "on_disk_bytes": baseline_on_disk_bytes,
191 },
192 "named_adapter": {
193 "setup_us": adapter_setup_us,
194 "build_us": adapter_build_us,
195 "exact_query_us": adapter_exact_query_us,
196 "approximate_query_us": adapter_approximate_query_us,
197 "exact_results": adapter_exact_results,
198 "approximate_results": adapter_approximate_results,
199 "exact_vectors_scored": adapter_exact_vectors_scored,
200 "approximate_vectors_scored": adapter_approximate_vectors_scored,
201 "throughput": adapter_throughput,
202 "historical_read_us": historical_read_us,
203 "historical_count": historical_count,
204 "on_disk_bytes": directory_bytes(adapter_dir.path())?,
205 }
206 });
207 fs::write(output, serde_json::to_vec_pretty(&report)?)?;
208 Ok(())
209}Sourcepub fn delete_filter(filter: Filter) -> Self
pub fn delete_filter(filter: Filter) -> Self
Creates a filter deletion mutation.
Trait Implementations§
Source§impl Clone for SnapshotMutation
impl Clone for SnapshotMutation
Source§impl Debug for SnapshotMutation
impl Debug for SnapshotMutation
Source§impl<'de> Deserialize<'de> for SnapshotMutation
impl<'de> Deserialize<'de> for SnapshotMutation
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Deserialize this value from the given Serde deserializer. Read more
Auto Trait Implementations§
impl Freeze for SnapshotMutation
impl RefUnwindSafe for SnapshotMutation
impl Send for SnapshotMutation
impl Sync for SnapshotMutation
impl Unpin for SnapshotMutation
impl UnsafeUnpin for SnapshotMutation
impl UnwindSafe for SnapshotMutation
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
Converts
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
Converts
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more