use std::collections::HashSet;
use tugraph::{
cursor::VertexCursor,
field::{FieldData, FieldSpec, FieldType},
txn::{TxnRead, TxnWrite},
types::DateTime,
};
mod common;
#[test]
fn test_search_with_index() {
let galaxy = common::open_galaxy_in_tmpdir().unwrap();
let graph = galaxy.open_graph("default", false).unwrap();
assert!(graph
.add_vertex_label(
"Person",
&[
FieldSpec {
name: "id".into(),
ty: FieldType::Int64,
optional: false,
},
FieldSpec {
name: "name".into(),
ty: FieldType::String,
optional: false,
},
FieldSpec {
name: "age".into(),
ty: FieldType::Int8,
optional: false,
},
],
"id",
)
.unwrap());
assert!(graph
.add_vertex_label(
"Comment",
&[
FieldSpec {
name: "id".into(),
ty: FieldType::Int64,
optional: false,
},
FieldSpec {
name: "content".into(),
ty: FieldType::String,
optional: false,
},
],
"id",
)
.unwrap());
assert!(graph
.add_edge_label(
"Post",
&[FieldSpec {
name: "datetime".into(),
ty: FieldType::DateTime,
optional: false,
},],
"",
[("Person", "Comment")]
)
.unwrap());
assert!(graph.add_vertex_index("Person", "age", false).unwrap());
assert!(graph.add_edge_index("Post", "datetime", false).unwrap());
const NUM_ALICE_POSTS: usize = 5;
{
let mut rw_txn = graph.create_rw_txn(false).unwrap();
let _bob = rw_txn
.add_vertex(
"Person",
&["id", "name", "age"],
&[
FieldData::Int64(0),
FieldData::String("Bob".into()),
FieldData::Int8(18),
],
)
.unwrap();
let _jack = rw_txn
.add_vertex(
"Person",
&["id", "name", "age"],
&[
FieldData::Int64(1),
FieldData::String("Jack".into()),
FieldData::Int8(21),
],
)
.unwrap();
let alice = rw_txn
.add_vertex(
"Person",
&["id", "name", "age"],
&[
FieldData::Int64(2),
FieldData::String("Alice".into()),
FieldData::Int8(17),
],
)
.unwrap();
(0..NUM_ALICE_POSTS).for_each(|i| {
let comment = rw_txn
.add_vertex(
"Comment",
&["id", "content"],
&[
FieldData::Int64(i as i64),
FieldData::String(format!("Alice's Comment {i}")),
],
)
.unwrap();
rw_txn
.add_edge(
alice,
comment,
"Post",
&["datetime"],
&[FieldData::DateTime(
DateTime::from_timestamp_opt(1000 + i as i64).unwrap(),
)],
)
.unwrap();
});
rw_txn.commit().unwrap();
}
{
let ro_txn = graph.create_ro_txn().unwrap();
assert!(ro_txn.is_vertex_indexed("Person", "age").unwrap());
assert!(!ro_txn.is_vertex_indexed("Comment", "content").unwrap());
assert!(ro_txn.is_edge_indexed("Post", "datetime").unwrap());
let v_indexes = ro_txn.all_vertex_indexes().unwrap();
assert_eq!(v_indexes.len(), 3);
assert_eq!(
v_indexes
.iter()
.map(|i| format!("{}.{}", i.label, i.field))
.collect::<HashSet<_>>(),
HashSet::from_iter(["Person.id".into(), "Person.age".into(), "Comment.id".into()])
);
let e_indexes = ro_txn.all_edge_indexes().unwrap();
assert_eq!(e_indexes.len(), 1);
assert_eq!(
e_indexes
.iter()
.map(|i| format!("{}.{}", i.label, i.field))
.collect::<HashSet<_>>(),
HashSet::from_iter(["Post.datetime".into()])
);
let ages: Vec<_> = ro_txn
.vertex_index_iter_values_from(
"Person",
"age",
&FieldData::Int8(18),
&FieldData::Int8(20),
)
.unwrap()
.collect();
assert_eq!(ages, vec![FieldData::Int8(18)]);
let post_times: Vec<_> = ro_txn
.edge_index_iter_values_from(
"Post",
"datetime",
&FieldData::DateTime(DateTime::from_timestamp_opt(1001).unwrap()),
&FieldData::DateTime(DateTime::from_timestamp_opt(2000).unwrap()),
)
.unwrap()
.collect();
assert_eq!(
post_times,
(0..NUM_ALICE_POSTS)
.map(|i| 1000 + i)
.filter(|i| (1001..2000).contains(i))
.map(|datetime| {
FieldData::DateTime(DateTime::from_timestamp_opt(datetime as i64).unwrap())
})
.collect::<Vec<_>>()
);
let primary_vertex_index = ro_txn
.unique_index_vertex_cur("Person", "id", &FieldData::Int64(1))
.unwrap();
assert!(primary_vertex_index.is_valid());
assert_eq!(
primary_vertex_index.field("name").unwrap(),
FieldData::String("Jack".into())
);
let person_lid = ro_txn.vertex_label_id("Person").unwrap();
let person_id_fid = ro_txn.vertex_field_id(person_lid, "id").unwrap();
let primary_vertex_index = ro_txn
.unique_index_vertex_cur_by_id(person_lid, person_id_fid, &FieldData::Int64(1))
.unwrap();
assert!(primary_vertex_index.is_valid());
assert_eq!(
primary_vertex_index.field("name").unwrap(),
FieldData::String("Jack".into())
);
}
}