Skip to content

Commit b99ba10

Browse files
committed
ARRAY_CONTAINS & Index selection
1 parent 0302d50 commit b99ba10

File tree

2 files changed

+135
-0
lines changed

2 files changed

+135
-0
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ enum_primitive = "*"
88
tempdir = "*"
99
lazy_static = "1.4.0"
1010
regex = "1.10.4"
11+
dirs = "^5"
1112

1213
[dev-dependencies.cargo-husky]
1314
version = "1"

tests/query_tests.rs

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,3 +212,137 @@ fn parameters() {
212212
assert_eq!(query.execute().unwrap().count(), 1);
213213
});
214214
}
215+
216+
#[test]
217+
fn array_contains() {
218+
use std::path::PathBuf;
219+
use std::time::Instant;
220+
221+
const DB_NAME: &str = "test_db";
222+
223+
let base_loc = dirs::data_local_dir()
224+
.unwrap()
225+
.to_str()
226+
.unwrap()
227+
.to_string();
228+
let dir = PathBuf::from(format!("{base_loc}/billeo"));
229+
230+
let cfg = DatabaseConfiguration {
231+
directory: dir.as_path(),
232+
encryption_key: None,
233+
};
234+
235+
if let Ok(db) = Database::open(DB_NAME, Some(cfg.clone())) {
236+
db.delete().unwrap();
237+
}
238+
239+
let mut db = Database::open(DB_NAME, Some(cfg)).expect("open db");
240+
assert!(Database::exists(DB_NAME, dir.as_path()));
241+
242+
// Add documents
243+
244+
// - Add Model1
245+
246+
for i in 0..25000 {
247+
let mut doc = Document::new_with_id(&format!("id_model1_{i}"));
248+
249+
let mut props = doc.mutable_properties();
250+
props.at("type").put_string("Model1");
251+
props.at("uselessField").put_i64(i);
252+
253+
let mut model2_ids = MutableArray::new();
254+
model2_ids
255+
.append()
256+
.put_string(&format!("id_model2_{}", 4 * i));
257+
model2_ids
258+
.append()
259+
.put_string(&format!("id_model2_{}", 4 * i + 1));
260+
model2_ids
261+
.append()
262+
.put_string(&format!("id_model2_{}", 4 * i + 2));
263+
model2_ids
264+
.append()
265+
.put_string(&format!("id_model2_{}", 4 * i + 3));
266+
props.at("model2Ids").put_value(&model2_ids);
267+
268+
db.save_document_with_concurency_control(&mut doc, ConcurrencyControl::FailOnConflict)
269+
.expect("save");
270+
}
271+
272+
// - Add Model2
273+
274+
for i in 0..100000 {
275+
let mut doc = Document::new_with_id(&format!("id_model2_{i}"));
276+
277+
let mut props = doc.mutable_properties();
278+
props.at("type").put_string("Model2");
279+
280+
db.save_document_with_concurency_control(&mut doc, ConcurrencyControl::FailOnConflict)
281+
.expect("save");
282+
}
283+
284+
// Run query
285+
286+
let query = Query::new(
287+
&db,
288+
QueryLanguage::N1QL,
289+
"SELECT _.* FROM _ \
290+
WHERE _.type='Model1' \
291+
AND ARRAY_CONTAINS(_.model2Ids, $model2Id)",
292+
)
293+
.expect("create query");
294+
295+
fn run_query(use_case: &str, query: &Query) {
296+
println!(
297+
"Explain for use case [{}]: {}",
298+
use_case,
299+
query.explain().unwrap()
300+
);
301+
302+
let start = Instant::now();
303+
304+
for i in 0..100 {
305+
let mut params = MutableDict::new();
306+
params
307+
.at("model2Id")
308+
.put_string(&format!("id_model2_{}", i * 100));
309+
query.set_parameters(&params);
310+
311+
assert_eq!(query.execute().unwrap().count(), 1);
312+
}
313+
314+
let stop = start.elapsed();
315+
316+
println!(
317+
"Query average time for use case [{}]: {:?}",
318+
use_case,
319+
stop / 100
320+
);
321+
}
322+
323+
// - No index
324+
325+
run_query("no index", &query);
326+
327+
// - Good index
328+
329+
assert!(db
330+
.create_index(
331+
"good_index",
332+
&ValueIndexConfiguration::new(QueryLanguage::JSON, r#"[[".type"], [".model2Ids"]]"#),
333+
)
334+
.unwrap());
335+
336+
run_query("good_index", &query);
337+
338+
// - Bad index
339+
340+
assert!(db
341+
.create_index(
342+
"bad_index",
343+
&ValueIndexConfiguration::new(QueryLanguage::JSON, r#"[[".type"], [".uselessField"]]"#),
344+
)
345+
.unwrap());
346+
347+
run_query("bad_index", &query);
348+
}

0 commit comments

Comments
 (0)