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> {
|
fn field_ids(&self) -> HashSet<&String> {
|
||||||
self.fields.keys().collect::<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> {
|
fn validate(&self, field_name: &str, value: Option<Field>) -> Result<Field, MTTError> {
|
||||||
@ -2089,6 +2090,7 @@ impl Query {
|
|||||||
|
|
||||||
fn field_ids(&self) -> HashSet<&String> {
|
fn field_ids(&self) -> HashSet<&String> {
|
||||||
self.data.keys().collect::<HashSet<&String>>()
|
self.data.keys().collect::<HashSet<&String>>()
|
||||||
|
//self.data.keys().cloned().collect::<HashSet<String>>()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2417,6 +2419,18 @@ impl Index {
|
|||||||
output
|
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) {
|
fn remove(&mut self, field: &Field, oid: &Oid) {
|
||||||
match self.data.get_mut(field) {
|
match self.data.get_mut(field) {
|
||||||
Some(oids) => {
|
Some(oids) => {
|
||||||
@ -2453,6 +2467,18 @@ impl Indexes {
|
|||||||
Self { data: output }
|
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) {
|
fn add_to_index(&mut self, field_name: &str, field: Field, oid: Oid) {
|
||||||
let index = match self.data.get_mut(field_name) {
|
let index = match self.data.get_mut(field_name) {
|
||||||
Some(data) => data,
|
Some(data) => data,
|
||||||
@ -2770,29 +2796,64 @@ impl DocumentFile {
|
|||||||
fn run_query(&self, query: &Query) -> Result<HashSet<Oid>, MTTError> {
|
fn run_query(&self, query: &Query) -> Result<HashSet<Oid>, MTTError> {
|
||||||
let query_ids = query.field_ids();
|
let query_ids = query.field_ids();
|
||||||
let doc_ids = self.docdef.field_ids();
|
let doc_ids = self.docdef.field_ids();
|
||||||
|
let index_ids = self.indexes.index_ids();
|
||||||
if !doc_ids.is_superset(&query_ids) {
|
if !doc_ids.is_superset(&query_ids) {
|
||||||
let missed = query_ids.difference(&doc_ids).last().unwrap();
|
let missed = query_ids.difference(&doc_ids).last().unwrap();
|
||||||
return Err(MTTError::DocumentFieldNotFound(missed.to_string()));
|
return Err(MTTError::DocumentFieldNotFound(missed.to_string()));
|
||||||
}
|
}
|
||||||
let mut oids: HashSet<Oid> = HashSet::new();
|
let used_indexed = index_ids
|
||||||
'docs: for (oid, doc) in self.docs.iter() {
|
.intersection(&query_ids)
|
||||||
for query_id in query_ids.iter() {
|
.cloned()
|
||||||
let doc_data = doc.get_field(query_id).unwrap();
|
.collect::<HashSet<&String>>();
|
||||||
let mut operation = query.get(query_id).unwrap();
|
let used_unindexed = query_ids
|
||||||
match operation.add_value(doc_data.clone()) {
|
.difference(&index_ids)
|
||||||
Ok(_) => {}
|
.cloned()
|
||||||
Err(err) => match err {
|
.collect::<HashSet<&String>>();
|
||||||
MTTError::DocumentFieldWrongDataType(got, expected) => {
|
let mut oids = HashSet::new();
|
||||||
return Err(MTTError::DocumentFieldWrongDataType(expected, got))
|
if used_indexed.is_empty() {
|
||||||
}
|
'docs: for (oid, doc) in self.docs.iter() {
|
||||||
_ => return Err(err),
|
for query_id in query_ids.iter() {
|
||||||
},
|
let doc_data = doc.get_field(query_id).unwrap();
|
||||||
}
|
let mut operation = query.get(query_id).unwrap();
|
||||||
if operation.calculate() == false.into() {
|
match operation.add_value(doc_data.clone()) {
|
||||||
continue 'docs;
|
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)
|
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]
|
#[test]
|
||||||
fn errors_on_bad_field_name() {
|
fn errors_on_bad_field_name() {
|
||||||
let (docdef, doc_name) = create_docdef(Vec::new());
|
let (docdef, doc_name) = create_docdef(Vec::new());
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user