Skip to content

Commit

Permalink
Define a query delta scope
Browse files Browse the repository at this point in the history
A delta scope defines a collection of deltas under a certain scope,
so that deltas can be organized depending on their context.

`context` is defined as a `u64` identifier.
`deltas` are stored by context now, and each context has a `BTreeMap`
of deltas by timestamp so that range operations are still possible.
  • Loading branch information
aleics committed Jan 14, 2025
1 parent 04d01d2 commit ccfa988
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 68 deletions.
5 changes: 3 additions & 2 deletions benches/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ use delta_search::fixtures::{
Sport,
};
use delta_search::query::{
CompositeFilter, OptionsQueryExecution, Pagination, QueryExecution, Sort, SortDirection,
CompositeFilter, OptionsQueryExecution, Pagination, QueryExecution, QueryScope, Sort,
SortDirection,
};
use delta_search::Engine;
use time::{Date, Month};
Expand Down Expand Up @@ -114,7 +115,7 @@ fn bench_apply_deltas(b: &mut Bencher) {
b.iter(move || {
tokio_test::block_on(async {
let query = QueryExecution::new()
.with_date(DATE.next_day().unwrap())
.with_scope(QueryScope::date(DATE.next_day().unwrap()))
.with_pagination(*PAGINATION);

ENGINE.query(&NAME, query).await.unwrap();
Expand Down
6 changes: 4 additions & 2 deletions examples/simple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use delta_search::fixtures::{
SwitchSportsDelta,
};
use delta_search::query::{
CompositeFilter, OptionsQueryExecution, QueryExecution, Sort, SortDirection,
CompositeFilter, OptionsQueryExecution, QueryExecution, QueryScope, Sort, SortDirection,
};
use delta_search::Engine;
use time::{Date, Month};
Expand Down Expand Up @@ -85,7 +85,9 @@ async fn main() {
FieldValue::String(Sport::Basketball.as_string()),
))
.with_sort(Sort::new("score").with_direction(SortDirection::DESC))
.with_date(Date::from_calendar_date(2024, Month::January, 1).unwrap());
.with_scope(QueryScope::date(
Date::from_calendar_date(2024, Month::January, 1).unwrap(),
));

let players = engine.query(name, query).await;

Expand Down
18 changes: 12 additions & 6 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use time::Date;
use tokio::sync::RwLock;

use query::QueryError;
use storage::StorageError;
use storage::{StorageError, StoredDeltaScope};

use crate::data::{DataItem, DataItemId};
use crate::query::{DeltaChange, FilterOption, OptionsQueryExecution, QueryExecution};
Expand Down Expand Up @@ -112,9 +112,11 @@ impl Engine {
date: Date,
deltas: &[DeltaChange],
) -> Result<(), EngineError> {
let scope = StoredDeltaScope::date(date);

if let Some(entry) = self.entities.get(name) {
let entity = entry.read().await;
entity.add_deltas(date, deltas)?;
entity.add_deltas(scope, deltas)?;
}
Ok(())
}
Expand Down Expand Up @@ -168,8 +170,8 @@ mod tests {
michael_jordan, roger, DecreaseScoreDelta, Player, Sport, SwitchSportsDelta, TestRunners,
};
use crate::query::{
CompositeFilter, FilterOption, OptionsQueryExecution, Pagination, QueryExecution, Sort,
SortDirection,
CompositeFilter, FilterOption, OptionsQueryExecution, Pagination, QueryExecution,
QueryScope, Sort, SortDirection,
};

lazy_static! {
Expand Down Expand Up @@ -507,7 +509,9 @@ mod tests {
// when
let execution = QueryExecution::new()
.with_filter(CompositeFilter::eq("sport", FieldValue::str("Football")))
.with_date(Date::from_calendar_date(2024, Month::January, 1).unwrap());
.with_scope(QueryScope::date(
Date::from_calendar_date(2024, Month::January, 1).unwrap(),
));

let mut matches = runner.engine.query(&runner.name, execution).await.unwrap();

Expand Down Expand Up @@ -559,7 +563,9 @@ mod tests {
// when
let execution = QueryExecution::new()
.with_filter(CompositeFilter::eq("sport", FieldValue::str("Football")))
.with_date(Date::from_calendar_date(2024, Month::January, 1).unwrap());
.with_scope(QueryScope::date(
Date::from_calendar_date(2024, Month::January, 1).unwrap(),
));

let mut matches = runner.engine.query(&runner.name, execution).await.unwrap();

Expand Down
56 changes: 37 additions & 19 deletions src/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,28 @@ impl FilterOption {
}
}

#[derive(Debug, PartialEq, Deserialize)]
pub struct QueryScope {
pub(crate) context: Option<u64>,
pub(crate) date: Date,
}

impl QueryScope {
pub fn date(date: Date) -> Self {
QueryScope {
context: None,
date,
}
}

pub fn context(context: u64, date: Date) -> Self {
QueryScope {
context: Some(context),
date,
}
}
}

#[derive(Debug)]
struct QueryIndices {
indices: EntityIndices,
Expand Down Expand Up @@ -95,7 +117,7 @@ impl QueryIndices {
#[derive(Default)]
pub struct OptionsQueryExecution {
filter: Option<CompositeFilter>,
date: Option<Date>,
scope: Option<QueryScope>,
ref_fields: Option<Vec<String>>,
}

Expand All @@ -113,18 +135,18 @@ impl OptionsQueryExecution {
self
}

pub fn with_date(mut self, date: Date) -> Self {
self.date = Some(date);
pub fn with_scope(mut self, scope: QueryScope) -> Self {
self.scope = Some(scope);
self
}

pub fn run(self, storage: &EntityStorage) -> Result<Vec<FilterOption>, QueryError> {
// Read the indices from storage. In case no fields are referenced, use all indices
// as filter options.
let indices = match (self.ref_fields, self.date) {
(Some(fields), Some(date)) => storage.read_indices_in(date, fields.as_slice()),
let indices = match (self.ref_fields, &self.scope) {
(Some(fields), Some(scope)) => storage.read_indices_in(scope, fields.as_slice()),
(Some(fields), None) => storage.read_current_indices(fields.as_slice()),
(None, Some(date)) => storage.read_all_indices_in(date),
(None, Some(scope)) => storage.read_all_indices_in(scope),
(None, None) => storage.read_all_current_indices(),
}?;

Expand All @@ -144,7 +166,7 @@ impl OptionsQueryExecution {
pub struct QueryExecution {
filter: Option<CompositeFilter>,
sort: Option<Sort>,
date: Option<Date>,
scope: Option<QueryScope>,
pagination: Option<Pagination>,
ref_fields: Vec<String>,
}
Expand All @@ -171,14 +193,14 @@ impl QueryExecution {
self
}

pub fn with_date(mut self, date: Date) -> Self {
self.date = Some(date);
pub fn with_scope(mut self, scope: QueryScope) -> Self {
self.scope = Some(scope);
self
}

pub fn run(self, storage: &EntityStorage) -> Result<Vec<DataItem>, QueryError> {
let indices = match self.date {
Some(date) => storage.read_indices_in(date, &self.ref_fields),
let indices = match &self.scope {
Some(scope) => storage.read_indices_in(scope, &self.ref_fields),
None => storage.read_current_indices(&self.ref_fields),
}?;

Expand Down Expand Up @@ -404,23 +426,19 @@ pub enum FilterOperation {
LessThanOrEqual(FieldValue),
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DeltaScope {
pub id: DataItemId,
pub field_name: String,
}

#[derive(Debug, Clone)]
pub struct DeltaChange {
pub scope: DeltaScope,
pub id: DataItemId,
pub field_name: String,
pub before: FieldValue,
pub after: FieldValue,
}

impl DeltaChange {
pub fn new(id: DataItemId, field_name: String, before: FieldValue, after: FieldValue) -> Self {
DeltaChange {
scope: DeltaScope { id, field_name },
id,
field_name,
before,
after,
}
Expand Down
Loading

0 comments on commit ccfa988

Please sign in to comment.