Made query work with indexes first.
Some checks failed
Gitea Actions Demo / Explore-Gitea-Actions (push) Failing after 1s
Some checks failed
Gitea Actions Demo / Explore-Gitea-Actions (push) Failing after 1s
This commit is contained in:
parent
0c2af3bc96
commit
1326fad904
176
src/message.rs
176
src/message.rs
@ -1395,6 +1395,7 @@ impl DocDef {
|
||||
|
||||
fn field_ids(&self) -> HashSet<&String> {
|
||||
self.fields.keys().collect::<HashSet<&String>>()
|
||||
//self.fields.keys().cloned().collect::<HashSet<String>>()
|
||||
}
|
||||
|
||||
fn validate(&self, field_name: &str, value: Option<Field>) -> Result<Field, MTTError> {
|
||||
@ -2089,6 +2090,7 @@ impl Query {
|
||||
|
||||
fn field_ids(&self) -> HashSet<&String> {
|
||||
self.data.keys().collect::<HashSet<&String>>()
|
||||
//self.data.keys().cloned().collect::<HashSet<String>>()
|
||||
}
|
||||
}
|
||||
|
||||
@ -2417,6 +2419,18 @@ impl Index {
|
||||
output
|
||||
}
|
||||
|
||||
fn pull(&self, calc: &Calculation) -> HashSet<Oid> {
|
||||
let mut output = HashSet::new();
|
||||
for (key, value) in self.data.iter() {
|
||||
let mut op = calc.clone();
|
||||
op.add_value(key.clone());
|
||||
if op.calculate() == true.into() {
|
||||
output = output.union(&value).cloned().collect();
|
||||
}
|
||||
}
|
||||
output
|
||||
}
|
||||
|
||||
fn remove(&mut self, field: &Field, oid: &Oid) {
|
||||
match self.data.get_mut(field) {
|
||||
Some(oids) => {
|
||||
@ -2453,6 +2467,18 @@ impl Indexes {
|
||||
Self { data: output }
|
||||
}
|
||||
|
||||
fn index_ids(&self) -> HashSet<&String> {
|
||||
self.data.keys().collect::<HashSet<&String>>()
|
||||
}
|
||||
|
||||
fn get_index(&self, field_id: &str) -> &Index {
|
||||
self.data.get(field_id).unwrap()
|
||||
}
|
||||
|
||||
fn pull(&self, field_id: &str, calc: &Calculation) -> HashSet<Oid> {
|
||||
self.get_index(field_id).pull(calc)
|
||||
}
|
||||
|
||||
fn add_to_index(&mut self, field_name: &str, field: Field, oid: Oid) {
|
||||
let index = match self.data.get_mut(field_name) {
|
||||
Some(data) => data,
|
||||
@ -2770,29 +2796,64 @@ impl DocumentFile {
|
||||
fn run_query(&self, query: &Query) -> Result<HashSet<Oid>, MTTError> {
|
||||
let query_ids = query.field_ids();
|
||||
let doc_ids = self.docdef.field_ids();
|
||||
let index_ids = self.indexes.index_ids();
|
||||
if !doc_ids.is_superset(&query_ids) {
|
||||
let missed = query_ids.difference(&doc_ids).last().unwrap();
|
||||
return Err(MTTError::DocumentFieldNotFound(missed.to_string()));
|
||||
}
|
||||
let mut oids: HashSet<Oid> = HashSet::new();
|
||||
'docs: for (oid, doc) in self.docs.iter() {
|
||||
for query_id in query_ids.iter() {
|
||||
let doc_data = doc.get_field(query_id).unwrap();
|
||||
let mut operation = query.get(query_id).unwrap();
|
||||
match operation.add_value(doc_data.clone()) {
|
||||
Ok(_) => {}
|
||||
Err(err) => match err {
|
||||
MTTError::DocumentFieldWrongDataType(got, expected) => {
|
||||
return Err(MTTError::DocumentFieldWrongDataType(expected, got))
|
||||
}
|
||||
_ => return Err(err),
|
||||
},
|
||||
}
|
||||
if operation.calculate() == false.into() {
|
||||
continue 'docs;
|
||||
let used_indexed = index_ids
|
||||
.intersection(&query_ids)
|
||||
.cloned()
|
||||
.collect::<HashSet<&String>>();
|
||||
let used_unindexed = query_ids
|
||||
.difference(&index_ids)
|
||||
.cloned()
|
||||
.collect::<HashSet<&String>>();
|
||||
let mut oids = HashSet::new();
|
||||
if used_indexed.is_empty() {
|
||||
'docs: for (oid, doc) in self.docs.iter() {
|
||||
for query_id in query_ids.iter() {
|
||||
let doc_data = doc.get_field(query_id).unwrap();
|
||||
let mut operation = query.get(query_id).unwrap();
|
||||
match operation.add_value(doc_data.clone()) {
|
||||
Ok(_) => {}
|
||||
Err(err) => match err {
|
||||
MTTError::DocumentFieldWrongDataType(got, expected) => {
|
||||
return Err(MTTError::DocumentFieldWrongDataType(expected, got))
|
||||
}
|
||||
_ => return Err(err),
|
||||
},
|
||||
}
|
||||
if operation.calculate() == false.into() {
|
||||
continue 'docs;
|
||||
}
|
||||
}
|
||||
oids.insert(oid.clone());
|
||||
}
|
||||
} else {
|
||||
let mut first_time = true;
|
||||
for field_id in used_indexed.iter() {
|
||||
let op = query.get(field_id).unwrap();
|
||||
let holder = self.indexes.pull(field_id, &op);
|
||||
if first_time {
|
||||
oids = holder;
|
||||
} else {
|
||||
oids = oids.intersection(&holder).cloned().collect();
|
||||
}
|
||||
first_time = false;
|
||||
}
|
||||
for field_id in used_unindexed.iter() {
|
||||
let mut holder: HashSet<Oid> = HashSet::new();
|
||||
for oid in oids.iter() {
|
||||
let doc = self.docs.get(oid).unwrap();
|
||||
let mut op = query.get(field_id).unwrap().clone();
|
||||
op.add_value(doc.get_field(field_id).unwrap());
|
||||
if op.calculate() == true.into() {
|
||||
holder.insert(oid.clone());
|
||||
}
|
||||
}
|
||||
oids = oids.intersection(&holder).cloned().collect();
|
||||
}
|
||||
oids.insert(oid.clone());
|
||||
}
|
||||
Ok(oids)
|
||||
}
|
||||
@ -3322,6 +3383,87 @@ mod document_files {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn query_should_work_with_multiple_inexed_fields() {
|
||||
let mut doc =
|
||||
TestDocument::new([FieldType::StaticString, FieldType::StaticString].to_vec());
|
||||
let docdef = doc.get_docdef_mut();
|
||||
docdef.add_index("field0".to_string(), IndexType::Index);
|
||||
docdef.add_index("field1".to_string(), IndexType::Index);
|
||||
doc.start();
|
||||
let values = [
|
||||
["a".into(), "a".into()].to_vec(),
|
||||
["a".into(), "b".into()].to_vec(),
|
||||
["b".into(), "a".into()].to_vec(),
|
||||
["b".into(), "b".into()].to_vec(),
|
||||
];
|
||||
for value in values.iter() {
|
||||
doc.populate(value.clone());
|
||||
}
|
||||
let mut query = Query::new();
|
||||
let mut calc = Calculation::new(Operand::Equal);
|
||||
calc.add_value("a");
|
||||
query.add("field0".to_string(), calc);
|
||||
let mut calc = Calculation::new(Operand::Equal);
|
||||
calc.add_value("b");
|
||||
query.add("field1".to_string(), calc);
|
||||
doc.send(query).unwrap();
|
||||
let result = doc.get_receiver().recv_timeout(TIMEOUT).unwrap();
|
||||
let action = result.get_action();
|
||||
match action {
|
||||
MsgAction::Reply(data) => {
|
||||
let afield: Field = "a".into();
|
||||
let bfield: Field = "b".into();
|
||||
assert_eq!(data.len(), 1, "should return one entry:\n{:?}", action);
|
||||
for doc in data.iter() {
|
||||
assert_eq!(doc.get_field("field0").unwrap(), afield);
|
||||
assert_eq!(doc.get_field("field1").unwrap(), bfield);
|
||||
}
|
||||
}
|
||||
_ => unreachable!("got {:?}: should have been a reply", action),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn query_should_work_with_mixed_inexed_fields() {
|
||||
let mut doc =
|
||||
TestDocument::new([FieldType::StaticString, FieldType::StaticString].to_vec());
|
||||
let docdef = doc.get_docdef_mut();
|
||||
docdef.add_index("field0".to_string(), IndexType::Index);
|
||||
doc.start();
|
||||
let values = [
|
||||
["a".into(), "a".into()].to_vec(),
|
||||
["a".into(), "b".into()].to_vec(),
|
||||
["b".into(), "a".into()].to_vec(),
|
||||
["b".into(), "b".into()].to_vec(),
|
||||
];
|
||||
for value in values.iter() {
|
||||
doc.populate(value.clone());
|
||||
}
|
||||
let mut query = Query::new();
|
||||
let mut calc = Calculation::new(Operand::Equal);
|
||||
calc.add_value("a");
|
||||
query.add("field0".to_string(), calc);
|
||||
let mut calc = Calculation::new(Operand::Equal);
|
||||
calc.add_value("b");
|
||||
query.add("field1".to_string(), calc);
|
||||
doc.send(query).unwrap();
|
||||
let result = doc.get_receiver().recv_timeout(TIMEOUT).unwrap();
|
||||
let action = result.get_action();
|
||||
match action {
|
||||
MsgAction::Reply(data) => {
|
||||
let afield: Field = "a".into();
|
||||
let bfield: Field = "b".into();
|
||||
assert_eq!(data.len(), 1, "should return one entry:\n{:?}", action);
|
||||
for doc in data.iter() {
|
||||
assert_eq!(doc.get_field("field0").unwrap(), afield);
|
||||
assert_eq!(doc.get_field("field1").unwrap(), bfield);
|
||||
}
|
||||
}
|
||||
_ => unreachable!("got {:?}: should have been a reply", action),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn errors_on_bad_field_name() {
|
||||
let (docdef, doc_name) = create_docdef(Vec::new());
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user