diff --git a/README.md b/README.md index 1ef7f4abb..070aa8a9a 100644 --- a/README.md +++ b/README.md @@ -133,15 +133,12 @@ You can also search through the graph to get back only certain elements based on let user: User = db .exec( QueryBuilder::select() - .values(User::db_keys()) - .ids( - QueryBuilder::search() - .from("users") - .where_() - .key("name") - .value(Equal("Bob".into())) - .query(), - ) + .elements::() + .search() + .from("users") + .where_() + .key("name") + .value(Equal("Bob".into())) .query(), )? .try_into()?; diff --git a/agdb/src/query/insert_values_query.rs b/agdb/src/query/insert_values_query.rs index ae1f66c28..2eab55829 100644 --- a/agdb/src/query/insert_values_query.rs +++ b/agdb/src/query/insert_values_query.rs @@ -1,4 +1,5 @@ use crate::query::query_values::QueryValues; +use crate::query_builder::search::SearchQueryBuilder; use crate::DbElement; use crate::DbId; use crate::DbImpl; @@ -8,6 +9,7 @@ use crate::QueryId; use crate::QueryIds; use crate::QueryMut; use crate::QueryResult; +use crate::SearchQuery; use crate::StorageData; /// Query to insert or update key-value pairs (properties) @@ -150,3 +152,28 @@ fn insert_values_id( } Ok(()) } + +impl SearchQueryBuilder for InsertValuesQuery { + fn search_mut(&mut self) -> &mut SearchQuery { + if let QueryIds::Search(search) = &mut self.ids { + search + } else { + panic!("Expected search query"); + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + #[should_panic] + fn missing_search() { + InsertValuesQuery { + values: QueryValues::Single(vec![]), + ids: QueryIds::Ids(vec![]), + } + .search_mut(); + } +} diff --git a/agdb/src/query/remove_query.rs b/agdb/src/query/remove_query.rs index 97d89ec7a..ab18d4f2a 100644 --- a/agdb/src/query/remove_query.rs +++ b/agdb/src/query/remove_query.rs @@ -1,8 +1,10 @@ +use crate::query_builder::search::SearchQueryBuilder; use crate::DbImpl; use crate::QueryError; use crate::QueryIds; use crate::QueryMut; use crate::QueryResult; +use crate::SearchQuery; use crate::StorageData; /// Query to remove database elements (nodes & edges). It @@ -53,3 +55,24 @@ impl QueryMut for &RemoveQuery { (*self).process(db) } } + +impl SearchQueryBuilder for RemoveQuery { + fn search_mut(&mut self) -> &mut SearchQuery { + if let QueryIds::Search(search) = &mut self.0 { + search + } else { + panic!("Expected search query"); + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + #[should_panic] + fn missing_search() { + RemoveQuery(QueryIds::Ids(vec![])).search_mut(); + } +} diff --git a/agdb/src/query/remove_values_query.rs b/agdb/src/query/remove_values_query.rs index 9b557fe75..992f0ffcd 100644 --- a/agdb/src/query/remove_values_query.rs +++ b/agdb/src/query/remove_values_query.rs @@ -1,8 +1,10 @@ +use crate::query_builder::search::SearchQueryBuilder; use crate::DbImpl; use crate::QueryError; use crate::QueryIds; use crate::QueryMut; use crate::QueryResult; +use crate::SearchQuery; use crate::SelectValuesQuery; use crate::StorageData; @@ -49,3 +51,28 @@ impl QueryMut for &RemoveValuesQuery { (*self).process(db) } } + +impl SearchQueryBuilder for RemoveValuesQuery { + fn search_mut(&mut self) -> &mut SearchQuery { + if let QueryIds::Search(search) = &mut self.0.ids { + search + } else { + panic!("Expected search query"); + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + #[should_panic] + fn missing_search() { + RemoveValuesQuery(SelectValuesQuery { + keys: vec![], + ids: QueryIds::Ids(vec![]), + }) + .search_mut(); + } +} diff --git a/agdb/src/query/search_query.rs b/agdb/src/query/search_query.rs index 4b1342005..ebbb6f36e 100644 --- a/agdb/src/query/search_query.rs +++ b/agdb/src/query/search_query.rs @@ -1,4 +1,5 @@ use crate::db::db_key_order::DbKeyOrder; +use crate::query_builder::search::SearchQueryBuilder; use crate::DbElement; use crate::DbId; use crate::DbImpl; @@ -212,6 +213,18 @@ impl SearchQuery { (_, _) => ids[self.offset as usize..(self.offset + self.limit) as usize].to_vec(), }) } + + pub(crate) fn new() -> Self { + Self { + algorithm: SearchQueryAlgorithm::BreadthFirst, + origin: QueryId::Id(DbId(0)), + destination: QueryId::Id(DbId(0)), + limit: 0, + offset: 0, + order_by: vec![], + conditions: vec![], + } + } } impl Query for &SearchQuery { @@ -220,6 +233,12 @@ impl Query for &SearchQuery { } } +impl SearchQueryBuilder for SearchQuery { + fn search_mut(&mut self) -> &mut SearchQuery { + self + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/agdb/src/query/select_aliases_query.rs b/agdb/src/query/select_aliases_query.rs index 7928c3c03..d331d3fce 100644 --- a/agdb/src/query/select_aliases_query.rs +++ b/agdb/src/query/select_aliases_query.rs @@ -1,3 +1,4 @@ +use crate::query_builder::search::SearchQueryBuilder; use crate::DbElement; use crate::DbImpl; use crate::Query; @@ -5,6 +6,7 @@ use crate::QueryError; use crate::QueryId; use crate::QueryIds; use crate::QueryResult; +use crate::SearchQuery; use crate::StorageData; /// Query to select aliases of given ids. All of the ids @@ -69,3 +71,24 @@ impl Query for &SelectAliasesQuery { (*self).process(db) } } + +impl SearchQueryBuilder for SelectAliasesQuery { + fn search_mut(&mut self) -> &mut SearchQuery { + if let QueryIds::Search(search) = &mut self.0 { + search + } else { + panic!("Expected search query"); + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + #[should_panic] + fn missing_search() { + SelectAliasesQuery(QueryIds::Ids(vec![])).search_mut(); + } +} diff --git a/agdb/src/query/select_edge_count_query.rs b/agdb/src/query/select_edge_count_query.rs index 8c701b06d..df88dddcb 100644 --- a/agdb/src/query/select_edge_count_query.rs +++ b/agdb/src/query/select_edge_count_query.rs @@ -1,9 +1,11 @@ +use crate::query_builder::search::SearchQueryBuilder; use crate::DbElement; use crate::DbImpl; use crate::Query; use crate::QueryError; use crate::QueryIds; use crate::QueryResult; +use crate::SearchQuery; use crate::StorageData; /// Query to select number of edges of given node ids. @@ -72,3 +74,29 @@ impl Query for &SelectEdgeCountQuery { (*self).process(db) } } + +impl SearchQueryBuilder for SelectEdgeCountQuery { + fn search_mut(&mut self) -> &mut SearchQuery { + if let QueryIds::Search(search) = &mut self.ids { + search + } else { + panic!("Expected search query"); + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + #[should_panic] + fn missing_search() { + SelectEdgeCountQuery { + ids: QueryIds::Ids(vec![]), + from: false, + to: false, + } + .search_mut(); + } +} diff --git a/agdb/src/query/select_key_count_query.rs b/agdb/src/query/select_key_count_query.rs index 148ae996e..e319883a3 100644 --- a/agdb/src/query/select_key_count_query.rs +++ b/agdb/src/query/select_key_count_query.rs @@ -1,9 +1,11 @@ +use crate::query_builder::search::SearchQueryBuilder; use crate::DbElement; use crate::DbImpl; use crate::Query; use crate::QueryError; use crate::QueryIds; use crate::QueryResult; +use crate::SearchQuery; use crate::StorageData; /// Query to select number of properties (key count) of @@ -55,3 +57,24 @@ impl Query for &SelectKeyCountQuery { (*self).process(db) } } + +impl SearchQueryBuilder for SelectKeyCountQuery { + fn search_mut(&mut self) -> &mut SearchQuery { + if let QueryIds::Search(search) = &mut self.0 { + search + } else { + panic!("Expected search query"); + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + #[should_panic] + fn missing_search() { + SelectKeyCountQuery(QueryIds::Ids(vec![])).search_mut(); + } +} diff --git a/agdb/src/query/select_keys_query.rs b/agdb/src/query/select_keys_query.rs index 2e3fef3e5..f5d892df9 100644 --- a/agdb/src/query/select_keys_query.rs +++ b/agdb/src/query/select_keys_query.rs @@ -1,9 +1,11 @@ +use crate::query_builder::search::SearchQueryBuilder; use crate::DbElement; use crate::DbImpl; use crate::Query; use crate::QueryError; use crate::QueryIds; use crate::QueryResult; +use crate::SearchQuery; use crate::StorageData; /// Query to select only property keys of given ids. All @@ -54,3 +56,24 @@ impl Query for &SelectKeysQuery { (*self).process(db) } } + +impl SearchQueryBuilder for SelectKeysQuery { + fn search_mut(&mut self) -> &mut SearchQuery { + if let QueryIds::Search(search) = &mut self.0 { + search + } else { + panic!("Expected search query"); + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + #[should_panic] + fn missing_search() { + SelectKeysQuery(QueryIds::Ids(vec![])).search_mut(); + } +} diff --git a/agdb/src/query/select_values_query.rs b/agdb/src/query/select_values_query.rs index b2162f6e4..998ccccac 100644 --- a/agdb/src/query/select_values_query.rs +++ b/agdb/src/query/select_values_query.rs @@ -1,3 +1,4 @@ +use crate::query_builder::search::SearchQueryBuilder; use crate::DbElement; use crate::DbImpl; use crate::DbValue; @@ -5,6 +6,7 @@ use crate::Query; use crate::QueryError; use crate::QueryIds; use crate::QueryResult; +use crate::SearchQuery; use crate::StorageData; /// Query to select elements with only certain properties of @@ -76,3 +78,28 @@ impl Query for &SelectValuesQuery { (*self).process(db) } } + +impl SearchQueryBuilder for SelectValuesQuery { + fn search_mut(&mut self) -> &mut SearchQuery { + if let QueryIds::Search(search) = &mut self.ids { + search + } else { + panic!("Expected search query"); + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + #[should_panic] + fn missing_search() { + SelectValuesQuery { + keys: vec![], + ids: QueryIds::Ids(vec![]), + } + .search_mut(); + } +} diff --git a/agdb/src/query_builder.rs b/agdb/src/query_builder.rs index 82d83b223..2295985d8 100644 --- a/agdb/src/query_builder.rs +++ b/agdb/src/query_builder.rs @@ -9,7 +9,7 @@ mod remove_aliases; mod remove_ids; mod remove_index; mod remove_values; -mod search; +pub mod search; mod select; mod select_aliases; mod select_edge_count; @@ -25,6 +25,7 @@ use self::insert::Insert; use self::remove::Remove; use self::search::Search; use self::select::Select; +use crate::SearchQuery; /// The starting point of all queries. /// @@ -99,8 +100,8 @@ impl QueryBuilder { /// QueryBuilder::search().depth_first(); /// QueryBuilder::search().elements(); /// ``` - pub fn search() -> Search { - Search {} + pub fn search() -> Search { + Search(SearchQuery::new()) } /// Selects data from the database: diff --git a/agdb/src/query_builder/insert_values.rs b/agdb/src/query_builder/insert_values.rs index bb752f191..15931a71b 100644 --- a/agdb/src/query_builder/insert_values.rs +++ b/agdb/src/query_builder/insert_values.rs @@ -1,5 +1,7 @@ +use crate::query_builder::search::Search; use crate::InsertValuesQuery; use crate::QueryIds; +use crate::SearchQuery; /// Insert values builder to set ids to which the values /// should be inserted. @@ -16,6 +18,13 @@ impl InsertValues { InsertValuesIds(self.0) } + + /// Inserts values into elements found using the search query. + /// Equivalent to `ids(QueryIds::Search(search)/*...*/)`. + pub fn search(mut self) -> Search { + self.0.ids = QueryIds::Search(SearchQuery::new()); + Search(self.0) + } } impl InsertValuesIds { diff --git a/agdb/src/query_builder/remove.rs b/agdb/src/query_builder/remove.rs index eaffa6072..503f1688b 100644 --- a/agdb/src/query_builder/remove.rs +++ b/agdb/src/query_builder/remove.rs @@ -4,11 +4,13 @@ use crate::query_builder::remove_aliases::RemoveAliases; use crate::query_builder::remove_ids::RemoveIds; use crate::query_builder::remove_index::RemoveIndex; use crate::query_builder::remove_values::RemoveValues; +use crate::query_builder::search::Search; use crate::DbValue; use crate::QueryIds; use crate::RemoveAliasesQuery; use crate::RemoveQuery; use crate::RemoveValuesQuery; +use crate::SearchQuery; use crate::SelectValuesQuery; /// Remove builder to choose what to delete from the database. @@ -38,6 +40,12 @@ impl Remove { RemoveIndex(key.into()) } + /// Remove the elements found using the search query. + /// Equivalent to `ids(QueryIds::Search(search)/*...*/)`. + pub fn search(self) -> Search { + Search(RemoveQuery(QueryIds::Search(SearchQuery::new()))) + } + /// List of keys to delete from ids selected in the next step. It is not an /// error if not all of the keys exist on the elements. /// diff --git a/agdb/src/query_builder/remove_values.rs b/agdb/src/query_builder/remove_values.rs index 6befc33c2..a94beeeb5 100644 --- a/agdb/src/query_builder/remove_values.rs +++ b/agdb/src/query_builder/remove_values.rs @@ -1,5 +1,7 @@ +use crate::query_builder::search::Search; use crate::QueryIds; use crate::RemoveValuesQuery; +use crate::SearchQuery; /// Remove values builder that lets you select the ids from /// which to remove the values. @@ -17,6 +19,13 @@ impl RemoveValues { RemoveValuesIds(self.0) } + + /// Remove the values from the elements found using the search query. + /// Equivalent to `ids(QueryIds::Search(search)/*...*/)`. + pub fn search(mut self) -> Search { + self.0 .0.ids = QueryIds::Search(SearchQuery::new()); + Search(self.0) + } } impl RemoveValuesIds { diff --git a/agdb/src/query_builder/search.rs b/agdb/src/query_builder/search.rs index c6ce79ceb..999db4dd3 100644 --- a/agdb/src/query_builder/search.rs +++ b/agdb/src/query_builder/search.rs @@ -4,43 +4,52 @@ use crate::Comparison; use crate::DbValue; use crate::QueryCondition; use crate::QueryConditionData; +use crate::QueryConditionLogic; +use crate::QueryConditionModifier; use crate::QueryId; use crate::SearchQuery; use crate::SearchQueryAlgorithm; +pub trait SearchQueryBuilder { + fn search_mut(&mut self) -> &mut SearchQuery; +} + /// Search builder query. -pub struct Search {} +pub struct Search(pub T); /// Search builder query that lets you choose search origin /// and other parameters. -pub struct SearchFrom(pub SearchQuery); +pub struct SearchFrom(pub T); /// Search builder query that lets you choose search destination /// and other parameters. -pub struct SearchTo(pub SearchQuery); +pub struct SearchTo(pub T); /// Search builder query that lets you choose an index to search -/// instead of the graph search entirely. -pub struct SearchIndex(pub DbValue); +/// instead of the graph search. +pub struct SearchIndex { + pub index: DbValue, + pub query: T, +} /// Search builder query that lets you choose a a value to find /// in the index. -pub struct SearchIndexValue(pub (DbValue, DbValue)); +pub struct SearchIndexValue(pub T); /// Search builder query that lets you choose limit and offset. -pub struct SearchOrderBy(pub SearchQuery); +pub struct SearchOrderBy(pub T); /// Search builder query that lets you choose conditions. -pub struct SelectLimit(pub SearchQuery); +pub struct SelectLimit(pub T); /// Search builder query that lets you choose limit. -pub struct SelectOffset(pub SearchQuery); +pub struct SelectOffset(pub T); /// Search builder query that lets you choose search origin /// and other parameters. -pub struct SearchAlgorithm(pub SearchQuery); +pub struct SearchAlgorithm(pub T); -impl Search { +impl Search { /// Use breadth-first (BFS) search algorithm. This option is redundant as /// BFS is the default. BFS means each level of the graph is examined in full /// before advancing to the next level. E.g. all edges coming from a node, @@ -55,16 +64,9 @@ impl Search { /// QueryBuilder::search().breadth_first().from(1); /// QueryBuilder::search().breadth_first().to(1); /// ``` - pub fn breadth_first(self) -> SearchAlgorithm { - SearchAlgorithm(SearchQuery { - algorithm: SearchQueryAlgorithm::BreadthFirst, - origin: QueryId::from(0), - destination: QueryId::from(0), - limit: 0, - offset: 0, - order_by: vec![], - conditions: vec![], - }) + pub fn breadth_first(mut self) -> SearchAlgorithm { + self.0.search_mut().algorithm = SearchQueryAlgorithm::BreadthFirst; + SearchAlgorithm(self.0) } /// Use depth-first (DFS) search algorithm. DFS means each element is followed @@ -79,16 +81,9 @@ impl Search { /// QueryBuilder::search().depth_first().from(1); /// QueryBuilder::search().depth_first().to(1); /// ``` - pub fn depth_first(self) -> SearchAlgorithm { - SearchAlgorithm(SearchQuery { - algorithm: SearchQueryAlgorithm::DepthFirst, - origin: QueryId::from(0), - destination: QueryId::from(0), - limit: 0, - offset: 0, - order_by: vec![], - conditions: vec![], - }) + pub fn depth_first(mut self) -> SearchAlgorithm { + self.0.search_mut().algorithm = SearchQueryAlgorithm::DepthFirst; + SearchAlgorithm(self.0) } /// Searches all elements (nodes & edges) in the database disregarding the graph @@ -96,7 +91,7 @@ impl Search { /// through the entire database which may be prohibitively expensive. Consider /// using `limit()`. /// - /// Note2: While the full range of conitions can be used some conditions do not + /// Note: While the full range of conitions can be used some conditions do not /// make logical sense (e.g. distance, beyond, edge_count etc.). /// /// Options: @@ -109,20 +104,26 @@ impl Search { /// QueryBuilder::search().elements().limit(10); /// QueryBuilder::search().elements().where_(); /// ``` - pub fn elements(self) -> SearchTo { - SearchTo(SearchQuery { - algorithm: SearchQueryAlgorithm::Elements, - origin: QueryId::from(0), - destination: QueryId::from(0), - limit: 0, - offset: 0, - order_by: vec![], - conditions: vec![], - }) + pub fn elements(mut self) -> SearchTo { + self.0.search_mut().algorithm = SearchQueryAlgorithm::Elements; + SearchTo(self.0) } - pub fn index>(self, key: T) -> SearchIndex { - SearchIndex(key.into()) + /// Searches an index specified by `key`. This is to provide fast lookup of + /// specific elements with particular key-value pair. + /// + /// Options: + /// + /// ``` + /// use agdb::QueryBuilder; + /// + /// QueryBuilder::search().index("k").value(1); + /// ``` + pub fn index>(self, key: K) -> SearchIndex { + SearchIndex { + index: key.into(), + query: self.0, + } } /// Sets the origin of the search. @@ -139,16 +140,9 @@ impl Search { /// QueryBuilder::search().from(1).limit(10); /// QueryBuilder::search().from(1).where_(); /// ``` - pub fn from>(self, id: T) -> SearchFrom { - SearchFrom(SearchQuery { - algorithm: SearchQueryAlgorithm::BreadthFirst, - origin: id.into(), - destination: QueryId::from(0), - limit: 0, - offset: 0, - order_by: vec![], - conditions: vec![], - }) + pub fn from>(mut self, id: I) -> SearchFrom { + self.0.search_mut().origin = id.into(); + SearchFrom(self.0) } /// Reverses the search setting only the destination. Reverse search @@ -164,20 +158,13 @@ impl Search { /// QueryBuilder::search().to(1).limit(10); /// QueryBuilder::search().to(1).where_(); /// ``` - pub fn to>(self, id: T) -> SearchTo { - SearchTo(SearchQuery { - algorithm: SearchQueryAlgorithm::BreadthFirst, - origin: QueryId::from(0), - destination: id.into(), - limit: 0, - offset: 0, - order_by: vec![], - conditions: vec![], - }) + pub fn to>(mut self, id: I) -> SearchTo { + self.0.search_mut().destination = id.into(); + SearchTo(self.0) } } -impl SearchAlgorithm { +impl SearchAlgorithm { /// Sets the origin of the search. /// /// Options: @@ -192,8 +179,8 @@ impl SearchAlgorithm { /// QueryBuilder::search().depth_first().from(1).limit(10); /// QueryBuilder::search().depth_first().from(1).where_(); /// ``` - pub fn from>(mut self, id: T) -> SearchFrom { - self.0.origin = id.into(); + pub fn from>(mut self, id: I) -> SearchFrom { + self.0.search_mut().origin = id.into(); SearchFrom(self.0) } @@ -210,13 +197,13 @@ impl SearchAlgorithm { /// QueryBuilder::search().depth_first().to(1).limit(10); /// QueryBuilder::search().depth_first().to(1).where_(); /// ``` - pub fn to>(mut self, id: T) -> SearchTo { - self.0.destination = id.into(); + pub fn to>(mut self, id: I) -> SearchTo { + self.0.search_mut().destination = id.into(); SearchTo(self.0) } } -impl SearchFrom { +impl SearchFrom { /// Sets the limit to number of ids returned. If during the search /// the `limit + offset` is hit the search ends and the result is returned. /// However when doing a path search or requesting ordering of the result @@ -230,9 +217,8 @@ impl SearchFrom { /// QueryBuilder::search().from(1).limit(10).query(); /// QueryBuilder::search().from(1).limit(10).where_(); /// ``` - pub fn limit(mut self, value: u64) -> SelectLimit { - self.0.limit = value; - + pub fn limit(mut self, value: u64) -> SelectLimit { + self.0.search_mut().limit = value; SelectLimit(self.0) } @@ -251,9 +237,8 @@ impl SearchFrom { /// QueryBuilder::search().from(1).offset(10).limit(5); /// QueryBuilder::search().from(1).offset(10).where_(); /// ``` - pub fn offset(mut self, value: u64) -> SelectOffset { - self.0.offset = value; - + pub fn offset(mut self, value: u64) -> SelectOffset { + self.0.search_mut().offset = value; SelectOffset(self.0) } @@ -269,14 +254,13 @@ impl SearchFrom { /// QueryBuilder::search().from(1).order_by([DbKeyOrder::Asc("k".into())]).limit(5); /// QueryBuilder::search().from(1).order_by([DbKeyOrder::Asc("k".into())]).where_(); /// ``` - pub fn order_by>(mut self, keys: T) -> SearchOrderBy { - self.0.order_by = Into::::into(keys).0; - + pub fn order_by>(mut self, keys: K) -> SearchOrderBy { + self.0.search_mut().order_by = Into::::into(keys).0; SearchOrderBy(self.0) } - /// Returns the built `SearchQuery` object. - pub fn query(self) -> SearchQuery { + /// Returns the built query object. + pub fn query(self) -> T { self.0 } @@ -294,9 +278,8 @@ impl SearchFrom { /// QueryBuilder::search().from(1).to(2).limit(5); /// QueryBuilder::search().from(1).to(2).where_(); /// ``` - pub fn to>(mut self, id: T) -> SearchTo { - self.0.destination = id.into(); - + pub fn to>(mut self, id: I) -> SearchTo { + self.0.search_mut().destination = id.into(); SearchTo(self.0) } @@ -321,12 +304,12 @@ impl SearchFrom { /// QueryBuilder::search().from(1).where_().beyond(); /// QueryBuilder::search().from(1).where_().not_beyond(); /// ``` - pub fn where_(self) -> Where { + pub fn where_(self) -> Where { Where::new(self.0) } } -impl SearchOrderBy { +impl SearchOrderBy { /// Sets the limit to number of ids returned. If during the search /// the `limit + offset` is hit the search ends and the result is returned. /// However when doing a path search or requesting ordering of the result @@ -340,9 +323,8 @@ impl SearchOrderBy { /// QueryBuilder::search().from(1).order_by([DbKeyOrder::Asc("k".into())]).limit(10).query(); /// QueryBuilder::search().from(1).order_by([DbKeyOrder::Asc("k".into())]).limit(10).where_(); /// ``` - pub fn limit(mut self, value: u64) -> SelectLimit { - self.0.limit = value; - + pub fn limit(mut self, value: u64) -> SelectLimit { + self.0.search_mut().limit = value; SelectLimit(self.0) } @@ -361,14 +343,13 @@ impl SearchOrderBy { /// QueryBuilder::search().from(1).order_by([DbKeyOrder::Asc("k".into())]).offset(10).limit(5); /// QueryBuilder::search().from(1).order_by([DbKeyOrder::Asc("k".into())]).offset(10).where_(); /// ``` - pub fn offset(mut self, value: u64) -> SelectOffset { - self.0.offset = value; - + pub fn offset(mut self, value: u64) -> SelectOffset { + self.0.search_mut().offset = value; SelectOffset(self.0) } - /// Returns the built `SearchQuery` object. - pub fn query(self) -> SearchQuery { + /// Returns the built query object. + pub fn query(self) -> T { self.0 } @@ -393,12 +374,12 @@ impl SearchOrderBy { /// QueryBuilder::search().from(1).where_().beyond(); /// QueryBuilder::search().from(1).where_().not_beyond(); /// ``` - pub fn where_(self) -> Where { + pub fn where_(self) -> Where { Where::new(self.0) } } -impl SearchTo { +impl SearchTo { /// Sets the limit to number of ids returned. If during the search /// the `limit + offset` is hit the search ends and the result is returned. /// However when doing a path search or requesting ordering of the result @@ -412,9 +393,8 @@ impl SearchTo { /// QueryBuilder::search().to(1).order_by([DbKeyOrder::Asc("k".into())]).limit(10).query(); /// QueryBuilder::search().to(1).order_by([DbKeyOrder::Asc("k".into())]).limit(10).where_(); /// ``` - pub fn limit(mut self, value: u64) -> SelectLimit { - self.0.limit = value; - + pub fn limit(mut self, value: u64) -> SelectLimit { + self.0.search_mut().limit = value; SelectLimit(self.0) } @@ -433,9 +413,8 @@ impl SearchTo { /// QueryBuilder::search().to(1).order_by([DbKeyOrder::Asc("k".into())]).offset(10).limit(5); /// QueryBuilder::search().to(1).order_by([DbKeyOrder::Asc("k".into())]).offset(10).where_(); /// ``` - pub fn offset(mut self, value: u64) -> SelectOffset { - self.0.offset = value; - + pub fn offset(mut self, value: u64) -> SelectOffset { + self.0.search_mut().offset = value; SelectOffset(self.0) } @@ -454,14 +433,13 @@ impl SearchTo { /// QueryBuilder::search().to(1).order_by([DbKeyOrder::Asc("k".into())]).offset(10).limit(5); /// QueryBuilder::search().to(1).order_by([DbKeyOrder::Asc("k".into())]).offset(10).where_(); /// ``` - pub fn order_by>(mut self, keys: T) -> SearchOrderBy { - self.0.order_by = Into::::into(keys).0; - + pub fn order_by>(mut self, keys: K) -> SearchOrderBy { + self.0.search_mut().order_by = Into::::into(keys).0; SearchOrderBy(self.0) } /// Returns the built `SearchQuery` object. - pub fn query(self) -> SearchQuery { + pub fn query(self) -> T { self.0 } @@ -486,14 +464,14 @@ impl SearchTo { /// QueryBuilder::search().from(1).where_().beyond(); /// QueryBuilder::search().from(1).where_().not_beyond(); /// ``` - pub fn where_(self) -> Where { + pub fn where_(self) -> Where { Where::new(self.0) } } -impl SelectLimit { - /// Returns the built `SearchQuery` object. - pub fn query(self) -> SearchQuery { +impl SelectLimit { + /// Returns the built query object. + pub fn query(self) -> T { self.0 } @@ -518,12 +496,12 @@ impl SelectLimit { /// QueryBuilder::search().from(1).where_().beyond(); /// QueryBuilder::search().from(1).where_().not_beyond(); /// ``` - pub fn where_(self) -> Where { + pub fn where_(self) -> Where { Where::new(self.0) } } -impl SelectOffset { +impl SelectOffset { /// Sets the limit to number of ids returned. If during the search /// the `limit + offset` is hit the search ends and the result is returned. /// However when doing a path search or requesting ordering of the result @@ -537,14 +515,13 @@ impl SelectOffset { /// QueryBuilder::search().from(1).offset(10).limit(10).query(); /// QueryBuilder::search().from(1).offset(10).limit(10).where_(); /// ``` - pub fn limit(mut self, value: u64) -> SelectLimit { - self.0.limit = value; - + pub fn limit(mut self, value: u64) -> SelectLimit { + self.0.search_mut().limit = value; SelectLimit(self.0) } - /// Returns the built `SearchQuery` object. - pub fn query(self) -> SearchQuery { + /// Returns the built query object. + pub fn query(self) -> T { self.0 } @@ -569,36 +546,30 @@ impl SelectOffset { /// QueryBuilder::search().from(1).where_().beyond(); /// QueryBuilder::search().from(1).where_().not_beyond(); /// ``` - pub fn where_(self) -> Where { + pub fn where_(self) -> Where { Where::new(self.0) } } -impl SearchIndex { +impl SearchIndex { /// Sets the value to be searched in the index. - pub fn value>(self, value: T) -> SearchIndexValue { - SearchIndexValue((self.0, value.into())) + pub fn value>(mut self, value: V) -> SearchIndexValue { + self.query.search_mut().algorithm = SearchQueryAlgorithm::Index; + self.query.search_mut().conditions.push(QueryCondition { + data: QueryConditionData::KeyValue { + key: self.index, + value: Comparison::Equal(value.into()), + }, + logic: QueryConditionLogic::And, + modifier: QueryConditionModifier::None, + }); + SearchIndexValue(self.query) } } -impl SearchIndexValue { - /// Returns the built `SearchQuery` object. - pub fn query(self) -> SearchQuery { - SearchQuery { - algorithm: SearchQueryAlgorithm::Index, - origin: QueryId::from(0), - destination: QueryId::from(0), - limit: 0, - offset: 0, - order_by: vec![], - conditions: vec![QueryCondition { - logic: crate::QueryConditionLogic::And, - modifier: crate::QueryConditionModifier::None, - data: QueryConditionData::KeyValue { - key: self.0 .0, - value: Comparison::Equal(self.0 .1), - }, - }], - } +impl SearchIndexValue { + /// Returns the built q object. + pub fn query(self) -> T { + self.0 } } diff --git a/agdb/src/query_builder/select.rs b/agdb/src/query_builder/select.rs index ecb0f3645..dfc8e9deb 100644 --- a/agdb/src/query_builder/select.rs +++ b/agdb/src/query_builder/select.rs @@ -1,4 +1,5 @@ use crate::db::db_value::DbValues; +use crate::query_builder::search::Search; use crate::query_builder::select_aliases::SelectAliases; use crate::query_builder::select_edge_count::SelectEdgeCount; use crate::query_builder::select_ids::SelectIds; @@ -107,6 +108,15 @@ impl Select { SelectNodeCount {} } + /// Select with all properties (key-values) using result + /// of the search query as ids. Equivalent to `ids(QueryBuilder::search()/* ... */)`. + pub fn search(self) -> Search { + Search(SelectValuesQuery { + keys: vec![], + ids: QueryIds::Search(crate::SearchQuery::new()), + }) + } + /// Select elements with `ids` with only `keys` properties (key-values). /// All ids specified must exist in the database. pub fn values>(self, keys: T) -> SelectValues { diff --git a/agdb/src/query_builder/select_aliases.rs b/agdb/src/query_builder/select_aliases.rs index d6b83c241..35cc3ae66 100644 --- a/agdb/src/query_builder/select_aliases.rs +++ b/agdb/src/query_builder/select_aliases.rs @@ -1,4 +1,6 @@ +use crate::query_builder::search::Search; use crate::QueryIds; +use crate::SearchQuery; use crate::SelectAliasesQuery; use crate::SelectAllAliasesQuery; @@ -18,6 +20,13 @@ impl SelectAliases { SelectAliasesIds(self.0) } + /// Select using the result of a search query as ids. + /// Equivalent to `ids(QueryBuilder::search()/* ... */)`. + pub fn search(mut self) -> Search { + self.0 .0 = QueryIds::Search(SearchQuery::new()); + Search(self.0) + } + /// Returns the built `SelectAllAliases` object. pub fn query(self) -> SelectAllAliasesQuery { SelectAllAliasesQuery {} diff --git a/agdb/src/query_builder/select_edge_count.rs b/agdb/src/query_builder/select_edge_count.rs index f636ad331..ed20cef91 100644 --- a/agdb/src/query_builder/select_edge_count.rs +++ b/agdb/src/query_builder/select_edge_count.rs @@ -1,3 +1,4 @@ +use crate::query_builder::search::Search; use crate::QueryIds; use crate::SelectEdgeCountQuery; @@ -16,6 +17,13 @@ impl SelectEdgeCount { SelectEdgeCountIds(self.0) } + + /// Select keys of elements returned from the search query. + /// Equivalent to `ids(QueryBuilder::search()/* ... */)`. + pub fn search(mut self) -> Search { + self.0.ids = QueryIds::Search(crate::SearchQuery::new()); + Search(self.0) + } } impl SelectEdgeCountIds { diff --git a/agdb/src/query_builder/select_key_count.rs b/agdb/src/query_builder/select_key_count.rs index de6824b7c..ee6d2f7cd 100644 --- a/agdb/src/query_builder/select_key_count.rs +++ b/agdb/src/query_builder/select_key_count.rs @@ -1,3 +1,4 @@ +use crate::query_builder::search::Search; use crate::QueryIds; use crate::SelectKeyCountQuery; @@ -16,6 +17,14 @@ impl SelectKeyCount { SelectKeyCountIds(self.0) } + + /// Select key count for elements returned from the search query. + /// Equivalent to `ids(QueryBuilder::search()/* ... */)`. + pub fn search(self) -> Search { + Search(SelectKeyCountQuery(QueryIds::Search( + crate::SearchQuery::new(), + ))) + } } impl SelectKeyCountIds { diff --git a/agdb/src/query_builder/select_keys.rs b/agdb/src/query_builder/select_keys.rs index c24998a96..079b51585 100644 --- a/agdb/src/query_builder/select_keys.rs +++ b/agdb/src/query_builder/select_keys.rs @@ -1,3 +1,4 @@ +use crate::query_builder::search::Search; use crate::QueryIds; use crate::SelectKeysQuery; @@ -16,6 +17,12 @@ impl SelectKeys { SelectKeysIds(self.0) } + + /// Select keys of elements returned from the search query. + /// Equivalent to `ids(QueryBuilder::search()/* ... */)`. + pub fn search(self) -> Search { + Search(SelectKeysQuery(QueryIds::Search(crate::SearchQuery::new()))) + } } impl SelectKeysIds { diff --git a/agdb/src/query_builder/select_values.rs b/agdb/src/query_builder/select_values.rs index 0968a194c..4dfe6016e 100644 --- a/agdb/src/query_builder/select_values.rs +++ b/agdb/src/query_builder/select_values.rs @@ -1,3 +1,4 @@ +use crate::query_builder::search::Search; use crate::QueryIds; use crate::SelectValuesQuery; @@ -16,6 +17,13 @@ impl SelectValues { SelectValuesIds(self.0) } + + /// Select using the result of a search query as ids. + /// Equivalent to `ids(QueryBuilder::search()/* ... */)`. + pub fn search(mut self) -> Search { + self.0.ids = QueryIds::Search(crate::SearchQuery::new()); + Search(self.0) + } } impl SelectValuesIds { diff --git a/agdb/src/query_builder/where_.rs b/agdb/src/query_builder/where_.rs index 65b85f1aa..78db89639 100644 --- a/agdb/src/query_builder/where_.rs +++ b/agdb/src/query_builder/where_.rs @@ -4,29 +4,29 @@ use crate::query::query_condition::QueryCondition; use crate::query::query_condition::QueryConditionData; use crate::query::query_condition::QueryConditionLogic; use crate::query::query_condition::QueryConditionModifier; -use crate::query::search_query::SearchQuery; +use crate::query_builder::search::SearchQueryBuilder; use crate::Comparison; use crate::DbValue; use crate::QueryIds; /// Condition builder -pub struct Where { +pub struct Where { logic: QueryConditionLogic, modifier: QueryConditionModifier, conditions: Vec>, - query: SearchQuery, + query: T, } /// Condition builder for `key` condition. -pub struct WhereKey { +pub struct WhereKey { key: DbValue, - where_: Where, + where_: Where, } /// Condition builder setting the logic operator. -pub struct WhereLogicOperator(pub Where); +pub struct WhereLogicOperator(pub Where); -impl Where { +impl Where { /// Sets the condition modifier for the following condition so /// that the search will continue beyond current element only /// if the condition is satisfied. For the opposite effect see @@ -47,9 +47,8 @@ impl Where { /// // Only edges or nodes with exactly 1 edge are followed. /// QueryBuilder::search().from(1).where_().beyond().edge().or().edge_count(CountComparison::Equal(1)); /// ``` - pub fn beyond(mut self) -> Where { + pub fn beyond(mut self) -> Self { self.modifier = QueryConditionModifier::Beyond; - self } @@ -68,7 +67,7 @@ impl Where { /// // Start accepting elements at distance greater than 1 (2+) /// QueryBuilder::search().from(1).where_().distance(CountComparison::GreaterThan(1)).query(); /// ``` - pub fn distance(mut self, comparison: CountComparison) -> WhereLogicOperator { + pub fn distance(mut self, comparison: CountComparison) -> WhereLogicOperator { self.add_condition(QueryCondition { logic: self.logic, modifier: self.modifier, @@ -87,7 +86,7 @@ impl Where { /// /// QueryBuilder::search().from(1).where_().edge().query(); /// ``` - pub fn edge(mut self) -> WhereLogicOperator { + pub fn edge(mut self) -> WhereLogicOperator { self.add_condition(QueryCondition { logic: self.logic, modifier: self.modifier, @@ -109,7 +108,7 @@ impl Where { /// /// QueryBuilder::search().from(1).where_().edge_count(CountComparison::Equal(1)).query(); /// ``` - pub fn edge_count(mut self, comparison: CountComparison) -> WhereLogicOperator { + pub fn edge_count(mut self, comparison: CountComparison) -> WhereLogicOperator { self.add_condition(QueryCondition { logic: self.logic, modifier: self.modifier, @@ -129,7 +128,7 @@ impl Where { /// /// QueryBuilder::search().from(1).where_().edge_count_from(CountComparison::Equal(1)).query(); /// ``` - pub fn edge_count_from(mut self, comparison: CountComparison) -> WhereLogicOperator { + pub fn edge_count_from(mut self, comparison: CountComparison) -> WhereLogicOperator { self.add_condition(QueryCondition { logic: self.logic, modifier: self.modifier, @@ -149,7 +148,7 @@ impl Where { /// /// QueryBuilder::search().from(1).where_().edge_count_to(CountComparison::Equal(1)).query(); /// ``` - pub fn edge_count_to(mut self, comparison: CountComparison) -> WhereLogicOperator { + pub fn edge_count_to(mut self, comparison: CountComparison) -> WhereLogicOperator { self.add_condition(QueryCondition { logic: self.logic, modifier: self.modifier, @@ -175,7 +174,7 @@ impl Where { /// // Do not continue the search beyond "alias" element /// QueryBuilder::search().from(1).where_().not_beyond().ids("alias").query(); /// ``` - pub fn ids>(mut self, ids: T) -> WhereLogicOperator { + pub fn ids>(mut self, ids: I) -> WhereLogicOperator { self.add_condition(QueryCondition { logic: self.logic, modifier: self.modifier, @@ -196,7 +195,7 @@ impl Where { /// // Includes only elements with property `String("k") == 1_i64` /// QueryBuilder::search().from(1).where_().key("k").value(Comparison::Equal(1.into())).query(); /// ``` - pub fn key>(self, key: T) -> WhereKey { + pub fn key>(self, key: K) -> WhereKey { WhereKey { key: key.into(), where_: self, @@ -218,7 +217,7 @@ impl Where { /// // Includes only elements with either "a" or "b" properties (keys). /// QueryBuilder::search().from(1).where_().keys("a").or().keys("b").query(); /// ``` - pub fn keys>(mut self, keys: T) -> WhereLogicOperator { + pub fn keys>(mut self, keys: K) -> WhereLogicOperator { self.add_condition(QueryCondition { logic: self.logic, modifier: self.modifier, @@ -237,7 +236,7 @@ impl Where { /// /// QueryBuilder::search().from(1).where_().node().query(); /// ``` - pub fn node(mut self) -> WhereLogicOperator { + pub fn node(mut self) -> WhereLogicOperator { self.add_condition(QueryCondition { logic: self.logic, modifier: self.modifier, @@ -327,7 +326,7 @@ impl Where { } } - pub(crate) fn new(query: SearchQuery) -> Self { + pub(crate) fn new(query: T) -> Self { Self { logic: QueryConditionLogic::And, modifier: QueryConditionModifier::None, @@ -360,9 +359,9 @@ impl Where { } } -impl WhereKey { +impl WhereKey { /// Sets the value of the `key` condition to `comparison`. - pub fn value(mut self, comparison: Comparison) -> WhereLogicOperator { + pub fn value(mut self, comparison: Comparison) -> WhereLogicOperator { let condition = QueryCondition { logic: self.where_.logic, modifier: self.where_.modifier, @@ -376,11 +375,11 @@ impl WhereKey { } } -impl WhereLogicOperator { +impl WhereLogicOperator { /// Sets the logic operator for the following condition /// to logical AND (&&). The condition passes only if /// both sides evaluates to `true`. - pub fn and(self) -> Where { + pub fn and(self) -> Where { Where { logic: QueryConditionLogic::And, modifier: QueryConditionModifier::None, @@ -392,7 +391,7 @@ impl WhereLogicOperator { /// Closes the current level condition level returning /// to the previous one. It semantically represents a /// closing bracket. - pub fn end_where(mut self) -> WhereLogicOperator { + pub fn end_where(mut self) -> WhereLogicOperator { self.0.collapse_conditions(); WhereLogicOperator(self.0) @@ -401,7 +400,7 @@ impl WhereLogicOperator { /// Sets the logic operator for the following condition /// to logical OR (||). The condition passes only if /// both sides evaluates to `false`. - pub fn or(self) -> Where { + pub fn or(self) -> Where { Where { logic: QueryConditionLogic::Or, modifier: QueryConditionModifier::None, @@ -411,9 +410,12 @@ impl WhereLogicOperator { } /// Returns the built `SearchQuery` object. - pub fn query(mut self) -> SearchQuery { + pub fn query(mut self) -> T { while self.0.collapse_conditions() {} - std::mem::swap(&mut self.0.query.conditions, &mut self.0.conditions[0]); + std::mem::swap( + &mut self.0.query.search_mut().conditions, + &mut self.0.conditions[0], + ); self.0.query } } @@ -421,25 +423,15 @@ impl WhereLogicOperator { #[cfg(test)] mod test { use super::*; - use crate::DbId; - use crate::QueryId; - use crate::SearchQueryAlgorithm; + use crate::SearchQuery; #[test] fn invalid_collapse() { - let mut where_ = Where { + let mut where_ = Where:: { logic: QueryConditionLogic::And, modifier: QueryConditionModifier::None, conditions: vec![vec![], vec![]], - query: SearchQuery { - algorithm: SearchQueryAlgorithm::BreadthFirst, - origin: QueryId::Id(DbId(0)), - destination: QueryId::Id(DbId(0)), - limit: 0, - offset: 0, - order_by: vec![], - conditions: vec![], - }, + query: SearchQuery::new(), }; assert!(!where_.collapse_conditions()); } diff --git a/agdb/tests/efficient_agdb.rs b/agdb/tests/efficient_agdb.rs index 9bc8d2dde..82f26d3cf 100644 --- a/agdb/tests/efficient_agdb.rs +++ b/agdb/tests/efficient_agdb.rs @@ -7,7 +7,6 @@ use agdb::Db; use agdb::DbId; use agdb::DbKeyOrder; use agdb::DbKeyValue; -use agdb::DbUserValue; use agdb::QueryBuilder; use agdb::QueryError; use agdb::QueryId; @@ -163,14 +162,11 @@ fn remove_like(db: &mut Db, user: DbId, id: DbId) -> Result<(), QueryError> { db.transaction_mut(|t| -> Result<(), QueryError> { t.exec_mut( QueryBuilder::remove() - .ids( - QueryBuilder::search() - .from(user) - .to(id) - .where_() - .keys("liked") - .query(), - ) + .search() + .from(user) + .to(id) + .where_() + .keys("liked") .query(), )?; Ok(()) @@ -182,18 +178,15 @@ fn login(db: &Db, username: &str, password: &str) -> Result { .exec( QueryBuilder::select() .values("password") - .ids( - QueryBuilder::search() - .depth_first() - .from("users") - .limit(1) - .where_() - .distance(CountComparison::Equal(2)) - .and() - .key("username") - .value(Equal(username.into())) - .query(), - ) + .search() + .depth_first() + .from("users") + .limit(1) + .where_() + .distance(CountComparison::Equal(2)) + .and() + .key("username") + .value(Equal(username.into())) .query(), )? .elements; @@ -242,16 +235,13 @@ fn posts(db: &Db, offset: u64, limit: u64) -> Result, QueryError> { Ok(db .exec( QueryBuilder::select() - .values(Post::db_keys()) - .ids( - QueryBuilder::search() - .from("posts") - .offset(offset) - .limit(limit) - .where_() - .distance(CountComparison::Equal(2)) - .query(), - ) + .elements::() + .search() + .from("posts") + .offset(offset) + .limit(limit) + .where_() + .distance(CountComparison::Equal(2)) .query(), )? .try_into()?) @@ -261,17 +251,14 @@ fn comments(db: &Db, id: DbId) -> Result, QueryError> { Ok(db .exec( QueryBuilder::select() - .values(Comment::db_keys()) - .ids( - QueryBuilder::search() - .depth_first() - .from(id) - .where_() - .node() - .and() - .distance(CountComparison::GreaterThan(1)) - .query(), - ) + .elements::() + .search() + .depth_first() + .from(id) + .where_() + .node() + .and() + .distance(CountComparison::GreaterThan(1)) .query(), )? .try_into()?) @@ -312,17 +299,14 @@ fn liked_posts(db: &Db, offset: u64, limit: u64) -> Result, Query Ok(db .exec( QueryBuilder::select() - .values(PostLiked::db_keys()) - .ids( - QueryBuilder::search() - .from("posts") - .order_by([DbKeyOrder::Desc("likes".into())]) - .offset(offset) - .limit(limit) - .where_() - .distance(CountComparison::Equal(2)) - .query(), - ) + .elements::() + .search() + .from("posts") + .order_by([DbKeyOrder::Desc("likes".into())]) + .offset(offset) + .limit(limit) + .where_() + .distance(CountComparison::Equal(2)) .query(), )? .try_into()?) @@ -332,13 +316,10 @@ fn mark_top_level_comments(db: &mut Db) -> Result<(), QueryError> { db.exec_mut( QueryBuilder::insert() .values_uniform([("level", 1).into()]) - .ids( - QueryBuilder::search() - .from("posts") - .where_() - .distance(CountComparison::Equal(4)) - .query(), - ) + .search() + .from("posts") + .where_() + .distance(CountComparison::Equal(4)) .query(), )?; Ok(()) diff --git a/agdb/tests/insert_values_test.rs b/agdb/tests/insert_values_test.rs index d92975e89..90427f2c2 100644 --- a/agdb/tests/insert_values_test.rs +++ b/agdb/tests/insert_values_test.rs @@ -239,6 +239,50 @@ fn insert_values_search() { ); } +#[test] +fn insert_values_search_alt() { + let mut db = TestDb::new(); + db.exec_mut(QueryBuilder::insert().nodes().count(3).query(), 3); + db.exec_mut(QueryBuilder::insert().edges().from(1).to(3).query(), 1); + db.exec_mut( + QueryBuilder::insert() + .values([ + [("key1", "value1").into()], + [("key2", "value2").into()], + [("key3", "value3").into()], + ]) + .search() + .from(1) + .query(), + 3, + ); + db.exec_elements( + QueryBuilder::select() + .ids(QueryBuilder::search().from(1).query()) + .query(), + &[ + DbElement { + id: DbId(1), + from: None, + to: None, + values: vec![("key1", "value1").into()], + }, + DbElement { + id: DbId(-4), + from: Some(DbId(1)), + to: Some(DbId(3)), + values: vec![("key2", "value2").into()], + }, + DbElement { + id: DbId(3), + from: None, + to: None, + values: vec![("key3", "value3").into()], + }, + ], + ); +} + #[test] fn insert_values_search_invalid_length() { let mut db = TestDb::new(); diff --git a/agdb/tests/quickstart.rs b/agdb/tests/quickstart.rs index 21947ba42..06ee29149 100644 --- a/agdb/tests/quickstart.rs +++ b/agdb/tests/quickstart.rs @@ -58,15 +58,12 @@ fn quickstart() -> Result<(), QueryError> { let user: User = db .exec( QueryBuilder::select() - .values(User::db_keys()) - .ids( - QueryBuilder::search() - .from("users") - .where_() - .key("name") - .value(Equal("Bob".into())) - .query(), - ) + .elements::() + .search() + .from("users") + .where_() + .key("name") + .value(Equal("Bob".into())) .query(), )? .try_into()?; diff --git a/agdb/tests/remove_index_test.rs b/agdb/tests/remove_index_test.rs index 9e6671d37..0c05cb751 100644 --- a/agdb/tests/remove_index_test.rs +++ b/agdb/tests/remove_index_test.rs @@ -25,7 +25,7 @@ fn remove_index_with_data() { } #[test] -fn rmove_missing_index() { +fn remove_missing_index() { let mut db = TestDb::new(); db.exec_mut(QueryBuilder::remove().index("username").query(), 0); } diff --git a/agdb/tests/remove_nodes_test.rs b/agdb/tests/remove_nodes_test.rs index 7b74b0a7e..139fc9c01 100644 --- a/agdb/tests/remove_nodes_test.rs +++ b/agdb/tests/remove_nodes_test.rs @@ -210,6 +210,17 @@ fn remove_nodes_search() { db.exec_error(QueryBuilder::select().ids(2).query(), "Id '2' not found"); } +#[test] +fn remove_nodes_search_alt() { + let mut db = TestDb::new(); + db.exec_mut(QueryBuilder::insert().nodes().count(2).query(), 2); + db.exec_mut_ids(QueryBuilder::insert().edges().from(1).to(2).query(), &[-3]); + + db.exec_mut(QueryBuilder::remove().search().from(1).query(), -2); + db.exec_error(QueryBuilder::select().ids(1).query(), "Id '1' not found"); + db.exec_error(QueryBuilder::select().ids(2).query(), "Id '2' not found"); +} + #[test] fn remove_nodes_removes_edges_with_all_values() { let mut db = TestDb::new(); diff --git a/agdb/tests/remove_values_test.rs b/agdb/tests/remove_values_test.rs index 133b083a0..5932ff20d 100644 --- a/agdb/tests/remove_values_test.rs +++ b/agdb/tests/remove_values_test.rs @@ -96,6 +96,44 @@ fn remove_values_search() { ); } +#[test] +fn remove_values_search_alt() { + let mut db = TestDb::new(); + db.exec_mut( + QueryBuilder::insert() + .nodes() + .values([[("key", 1).into()], [("key", 2).into()]]) + .query(), + 2, + ); + db.exec_mut(QueryBuilder::insert().edges().from(1).to(2).query(), 1); + db.exec_mut( + QueryBuilder::remove() + .values("key") + .search() + .from(1) + .query(), + -2, + ); + db.exec_elements( + QueryBuilder::select().ids([1, 2]).query(), + &[ + DbElement { + id: DbId(1), + from: None, + to: None, + values: vec![], + }, + DbElement { + id: DbId(2), + from: None, + to: None, + values: vec![], + }, + ], + ); +} + #[test] fn remove_missing_key() { let mut db = TestDb::new(); diff --git a/agdb/tests/select_aliases_test.rs b/agdb/tests/select_aliases_test.rs index 359dbb1c8..9505e3627 100644 --- a/agdb/tests/select_aliases_test.rs +++ b/agdb/tests/select_aliases_test.rs @@ -131,6 +131,50 @@ fn select_aliases_search() { ); } +#[test] +fn select_aliases_search_alt() { + let mut db = TestDb::new(); + + db.exec_mut( + QueryBuilder::insert() + .nodes() + .aliases(["alias1", "alias2", "alias3", "alias4", "alias5"]) + .query(), + 5, + ); + db.exec_mut( + QueryBuilder::insert() + .edges() + .from([1, 3]) + .to([3, 5]) + .values_uniform([ + ("key1", 1).into(), + ("key2", 10).into(), + ("key3", 100).into(), + ]) + .query(), + 2, + ); + + db.exec_elements( + QueryBuilder::select().aliases().search().from(3).query(), + &[ + DbElement { + id: DbId(3), + from: None, + to: None, + values: vec![("alias", "alias3").into()], + }, + DbElement { + id: DbId(5), + from: None, + to: None, + values: vec![("alias", "alias5").into()], + }, + ], + ); +} + #[test] fn select_all_aliases_empty() { let db = TestDb::new(); diff --git a/agdb/tests/select_edge_count_test.rs b/agdb/tests/select_edge_count_test.rs index 1d8e861c2..d59c59f86 100644 --- a/agdb/tests/select_edge_count_test.rs +++ b/agdb/tests/select_edge_count_test.rs @@ -201,6 +201,74 @@ fn select_edge_count_search() { ); } +#[test] +fn select_edge_count_search_alt() { + let mut db = TestDb::new(); + db.exec_mut( + QueryBuilder::insert() + .nodes() + .aliases(["node1", "node2", "node3"]) + .query(), + 3, + ); + db.exec_mut( + QueryBuilder::insert() + .edges() + .from(["node1", "node3", "node2", "node2"]) + .to(["node3", "node2", "node1", "node2"]) + .query(), + 4, + ); + + db.exec_elements( + QueryBuilder::select() + .edge_count() + .search() + .from("node1") + .where_() + .edge_count(CountComparison::Equal(4)) + .query(), + &[DbElement { + id: DbId(2), + from: None, + to: None, + values: vec![("edge_count", 4_u64).into()], + }], + ); + + db.exec_elements( + QueryBuilder::select() + .edge_count_from() + .search() + .from("node1") + .where_() + .edge_count(CountComparison::Equal(4)) + .query(), + &[DbElement { + id: DbId(2), + from: None, + to: None, + values: vec![("edge_count", 2_u64).into()], + }], + ); + + db.exec_elements( + QueryBuilder::select() + .edge_count_to() + .search() + .from("node1") + .where_() + .edge_count(CountComparison::Equal(4)) + .query(), + &[DbElement { + id: DbId(2), + from: None, + to: None, + values: vec![("edge_count", 2_u64).into()], + }], + ); +} + #[test] fn select_edge_count_non_nodes() { let mut db = TestDb::new(); diff --git a/agdb/tests/select_key_count_test.rs b/agdb/tests/select_key_count_test.rs index 655c10670..ee55ff705 100644 --- a/agdb/tests/select_key_count_test.rs +++ b/agdb/tests/select_key_count_test.rs @@ -47,7 +47,7 @@ fn select_keys_count_no_keys() { } #[test] -fn select_keys_search() { +fn select_key_count_search() { let mut db = TestDb::new(); let values = vec![ @@ -101,3 +101,56 @@ fn select_keys_search() { ], ); } + +#[test] +fn select_key_count_search_alt() { + let mut db = TestDb::new(); + + let values = vec![ + ("key1", 1).into(), + ("key2", 10).into(), + ("key3", 100).into(), + ]; + + db.exec_mut( + QueryBuilder::insert() + .nodes() + .count(5) + .values_uniform(values.clone()) + .query(), + 5, + ); + db.exec_mut( + QueryBuilder::insert() + .edges() + .from([1, 3]) + .to([3, 5]) + .values_uniform(values) + .query(), + 2, + ); + + db.exec_elements( + QueryBuilder::select().key_count().search().from(3).query(), + &[ + DbElement { + id: DbId(3), + from: None, + to: None, + values: vec![("key_count", 3_u64).into()], + }, + DbElement { + id: DbId(-7), + from: Some(DbId(3)), + to: Some(DbId(5)), + values: vec![("key_count", 3_u64).into()], + }, + DbElement { + id: DbId(5), + from: None, + to: None, + values: vec![("key_count", 3_u64).into()], + }, + ], + ); +} diff --git a/agdb/tests/select_keys.rs b/agdb/tests/select_keys.rs index fff8ced2e..b64402ef3 100644 --- a/agdb/tests/select_keys.rs +++ b/agdb/tests/select_keys.rs @@ -111,3 +111,61 @@ fn select_keys_search() { ], ); } + +#[test] +fn select_keys_search_alt() { + let mut db = TestDb::new(); + + db.exec_mut( + QueryBuilder::insert() + .nodes() + .count(5) + .values_uniform([ + ("key1", 1).into(), + ("key2", 10).into(), + ("key3", 100).into(), + ]) + .query(), + 5, + ); + db.exec_mut( + QueryBuilder::insert() + .edges() + .from([1, 3]) + .to([3, 5]) + .query(), + 2, + ); + + db.exec_elements( + QueryBuilder::select().keys().search().from(3).query(), + &[ + DbElement { + id: DbId(3), + from: None, + to: None, + values: vec![ + ("key1", DbValue::default()).into(), + ("key2", DbValue::default()).into(), + ("key3", DbValue::default()).into(), + ], + }, + DbElement { + id: DbId(-7), + from: Some(DbId(3)), + to: Some(DbId(5)), + values: vec![], + }, + DbElement { + id: DbId(5), + from: None, + to: None, + values: vec![ + ("key1", DbValue::default()).into(), + ("key2", DbValue::default()).into(), + ("key3", DbValue::default()).into(), + ], + }, + ], + ); +} diff --git a/agdb/tests/select_test.rs b/agdb/tests/select_test.rs index 7eb0af8c8..d7eba2656 100644 --- a/agdb/tests/select_test.rs +++ b/agdb/tests/select_test.rs @@ -1,5 +1,7 @@ mod test_db; +use agdb::DbElement; +use agdb::DbId; use agdb::QueryBuilder; use test_db::TestDb; @@ -74,3 +76,60 @@ fn select_from_search() { &[1, -6, 3, -7, 5], ); } + +#[test] +fn select_embedded_search() { + let mut db = TestDb::new(); + + db.exec_mut( + QueryBuilder::insert() + .nodes() + .aliases(["alias1", "alias2", "alias3", "alias4", "alias5"]) + .values([ + [("k", 1).into()], + [("k", 2).into()], + [("k", 3).into()], + [("k", 4).into()], + [("k", 5).into()], + ]) + .query(), + 5, + ); + db.exec_mut( + QueryBuilder::insert() + .edges() + .from(["alias1", "alias3"]) + .to(["alias3", "alias5"]) + .query(), + 2, + ); + + db.exec_elements( + QueryBuilder::select() + .search() + .from("alias1") + .where_() + .node() + .query(), + &[ + DbElement { + id: DbId(1), + from: None, + to: None, + values: vec![("k", 1).into()], + }, + DbElement { + id: DbId(3), + from: None, + to: None, + values: vec![("k", 3).into()], + }, + DbElement { + id: DbId(5), + from: None, + to: None, + values: vec![("k", 5).into()], + }, + ], + ); +} diff --git a/agdb/tests/select_values_test.rs b/agdb/tests/select_values_test.rs index b7ea79ddb..c5a5b8de3 100644 --- a/agdb/tests/select_values_test.rs +++ b/agdb/tests/select_values_test.rs @@ -128,3 +128,57 @@ fn select_values_search() { ], ); } + +#[test] +fn select_values_search_alt() { + let mut db = TestDb::new(); + + db.exec_mut( + QueryBuilder::insert() + .nodes() + .count(5) + .values_uniform([ + ("key1", 1).into(), + ("key2", 10).into(), + ("key3", 100).into(), + ]) + .query(), + 5, + ); + db.exec_mut( + QueryBuilder::insert() + .edges() + .from([1, 3]) + .to([3, 5]) + .query(), + 2, + ); + + db.exec_elements( + QueryBuilder::select() + .values("key2") + .search() + .from(3) + .query(), + &[ + DbElement { + id: DbId(3), + from: None, + to: None, + values: vec![("key2", 10).into()], + }, + DbElement { + id: DbId(-7), + from: Some(DbId(3)), + to: Some(DbId(5)), + values: vec![], + }, + DbElement { + id: DbId(5), + from: None, + to: None, + values: vec![("key2", 10).into()], + }, + ], + ); +} diff --git a/agdb_web/pages/docs/guides/quickstart.en-US.mdx b/agdb_web/pages/docs/guides/quickstart.en-US.mdx index 515f6c5ab..75ae56524 100644 --- a/agdb_web/pages/docs/guides/quickstart.en-US.mdx +++ b/agdb_web/pages/docs/guides/quickstart.en-US.mdx @@ -111,16 +111,13 @@ db.exec_mut( let users: Vec = db .exec( QueryBuilder::select() - .values(User::db_keys()) // Select only relevant properties for the User struct. - .ids( - QueryBuilder::search() - .from("users") // Start the search from the "users" node. - .where_() - .key("age") // Examine "age" property. - .value(LessThan(40.into())) // Include it in the search result if the value - // is less than 40. - .query(), - ) + .elements::() // Select only relevant properties for the User struct. + .search() + .from("users") // Start the search from the "users" node. + .where_() + .key("age") // Examine "age" property. + .value(LessThan(40.into())) // Include it in the search result if the value + // is less than 40. .query(), )? .try_into()?; // Convert the result into a list of User objects. diff --git a/agdb_web/pages/docs/references/efficient-agdb.en-US.md b/agdb_web/pages/docs/references/efficient-agdb.en-US.md index d413249df..8d4bd3f0e 100644 --- a/agdb_web/pages/docs/references/efficient-agdb.en-US.md +++ b/agdb_web/pages/docs/references/efficient-agdb.en-US.md @@ -230,14 +230,11 @@ fn remove_like(db: &mut Db, user: DbId, id: DbId) -> Result<(), QueryError> { db.transaction_mut(|t| -> Result<(), QueryError> { t.exec_mut( QueryBuilder::remove() - .ids( - QueryBuilder::search() - .from(user) - .to(id) - .where_() - .keys(vec!["liked".into()]) - .query(), - ) + .search() + .from(user) + .to(id) + .where_() + .keys(vec!["liked".into()]) .query(), )?; Ok(()) @@ -282,18 +279,15 @@ fn login(db: &Db, username: &str, password: &str) -> Result { .exec( QueryBuilder::select() .values("password".into()) - .ids( - QueryBuilder::search() - .depth_first() - .from("users") - .limit(1) - .where_() - .distance(CountComparison::Equal(2)) - .and() - .key("username") - .value(Equal(username.into())) - .query(), - ) + .search() + .depth_first() + .from("users") + .limit(1) + .where_() + .distance(CountComparison::Equal(2)) + .and() + .key("username") + .value(Equal(username.into())) .query(), )? .elements; @@ -385,16 +379,13 @@ fn posts(db: &Db, offset: u64, limit: u64) -> Result, QueryError> { Ok(db .exec( QueryBuilder::select() - .values(Post::db_keys()) - .ids( - QueryBuilder::search() - .from("posts") - .offset(offset) - .limit(limit) - .where_() - .distance(CountComparison::Equal(2)) - .query(), - ) + .elements::() + .search() + .from("posts") + .offset(offset) + .limit(limit) + .where_() + .distance(CountComparison::Equal(2)) .query(), )? .try_into()?) @@ -414,17 +405,14 @@ fn comments(db: &Db, id: DbId) -> Result, QueryError> { Ok(db .exec( QueryBuilder::select() - .values(Comment::db_keys()) - .ids( - QueryBuilder::search() - .depth_first() - .from(id) - .where_() - .node() - .and() - .distance(CountComparison::GreaterThan(1)) - .query(), - ) + .elements::() + .search() + .depth_first() + .from(id) + .where_() + .node() + .and() + .distance(CountComparison::GreaterThan(1)) .query(), )? .try_into()?) @@ -460,6 +448,7 @@ fn add_likes_to_posts(db: &mut Db) -> Result<(), QueryError> { .distance(CountComparison::Equal(2)) .query(), )?; + let mut likes = Vec::>::new(); for post in posts.ids() { @@ -502,17 +491,14 @@ fn liked_posts(db: &Db, offset: u64, limit: u64) -> Result, Query Ok(db .exec( QueryBuilder::select() - .values(PostLiked::db_keys()) - .ids( - QueryBuilder::search() - .from("posts") - .order_by([DbKeyOrder::Desc("likes".into())]) - .offset(offset) - .limit(limit) - .where_() - .distance(CountComparison::Equal(2)) - .query(), - ) + .elements::() + .search() + .from("posts") + .order_by([DbKeyOrder::Desc("likes".into())]) + .offset(offset) + .limit(limit) + .where_() + .distance(CountComparison::Equal(2)) .query(), )? .try_into()?) @@ -530,13 +516,10 @@ fn mark_top_level_comments(db: &mut Db) -> Result<(), QueryError> { db.exec_mut( QueryBuilder::insert() .values_uniform([("level", 1).into()]) - .ids( - QueryBuilder::search() - .from("posts") - .where_() - .distance(CountComparison::Equal(4)) - .query(), - ) + .search() + .from("posts") + .where_() + .distance(CountComparison::Equal(4)) .query(), )?; Ok(()) diff --git a/agdb_web/pages/docs/references/queries.en-US.md b/agdb_web/pages/docs/references/queries.en-US.md index 2e19bac2e..08bb0dd2b 100644 --- a/agdb_web/pages/docs/references/queries.en-US.md +++ b/agdb_web/pages/docs/references/queries.en-US.md @@ -521,8 +521,10 @@ QueryBuilder::insert().element(&T { ... }).query(); //Where T: DbUserValue (i.e. QueryBuilder::insert().elements(&vec![T {...}, T {...}]).query(); //Where T: DbUserValue (i.e. #derive(UserValue)) QueryBuilder::insert().values([vec![("k", "v").into(), (1, 10).into()], vec![("k", 2).into()]]).ids([1, 2]).query(); QueryBuilder::insert().values([vec![("k", "v").into(), (1, 10).into()], vec![("k", 2).into()]]).ids(QueryBuilder::search().from("a").query()).query(); +QueryBuilder::insert().values([vec![("k", "v").into(), (1, 10).into()], vec![("k", 2).into()]]).search().from("a").query(); //Equivalent to the previous query QueryBuilder::insert().values_uniform([("k", "v").into(), (1, 10).into()]).ids([1, 2]).query(); QueryBuilder::insert().values_uniform([("k", "v").into(), (1, 10).into()]).ids(QueryBuilder::search().from("a").query()).query(); +QueryBuilder::insert().values_uniform([("k", "v").into(), (1, 10).into()]).search().from("a").query(); //Equivalent to the previous query ``` @@ -600,6 +602,7 @@ QueryBuilder::remove().ids("a").query(); QueryBuilder::remove().ids([1, 2]).query(); QueryBuilder::remove().ids(["a", "b"]).query(); QueryBuilder::remove().ids(QueryBuilder::search().from("a").query()).query(); +QueryBuilder::remove().search().from("a").query(); //Equivalent to the previous query ``` @@ -659,6 +662,7 @@ pub struct QueryResult { ```rs QueryBuilder::remove().values(["k1".into(), "k2".into()]).ids([1, 2]).query(); QueryBuilder::remove().values(["k1".into(), "k2".into()]).ids(QueryBuilder::search().from("a").query()).query(); +QueryBuilder::remove().values(["k1".into(), "k2".into()]).search().from("a").query(); //Equivalent to the previous query ``` @@ -705,6 +709,7 @@ pub struct QueryResult { ```rs QueryBuilder::select().aliases().ids([1, 2]).query(); QueryBuilder::select().aliases().ids(QueryBuilder::search().from(1).query()).query(); +QueryBuilder::select().aliases().search().from(1).query(); //Equivalent to the previous query ``` @@ -771,6 +776,8 @@ pub struct QueryResult { QueryBuilder::select().edge_count().ids([1, 2]).query(); QueryBuilder::select().edge_count_from().ids([1, 2]).query(); QueryBuilder::select().edge_count_to().ids([1, 2]).query(); +QueryBuilder::select().edge_count().ids(QueryBuilder::search().from("a").query()).query(); +QueryBuilder::select().edge_count().search().from("a").query(); // Equivalent to the previous query ``` @@ -836,6 +843,7 @@ pub struct QueryResult { QueryBuilder::select().keys().ids("a").query(); QueryBuilder::select().keys().ids([1, 2]).query(); QueryBuilder::select().keys().ids(QueryBuilder::search().from(1).query()).query(); +QueryBuilder::select().keys().search().from(1).query(); // Equivalent to the previous query ``` @@ -868,6 +876,7 @@ pub struct QueryResult { QueryBuilder::select().key_count().ids("a").query(); QueryBuilder::select().key_count().ids([1, 2]).query(); QueryBuilder::select().key_count().ids(QueryBuilder::search().from(1).query()).query(); +QueryBuilder::select().key_count().search().from(1).query(); // Equivalent to the previous query ``` @@ -927,13 +936,18 @@ pub struct QueryResult { Builder ```rs + QueryBuilder::select().ids("a").query(); QueryBuilder::select().ids([1, 2]).query(); QueryBuilder::select().ids(QueryBuilder::search().from(1).query()).query(); +QueryBuilder::select().search().from(1).query(); // Equivalent to the previous query QueryBuilder::select().values(["k".into(), "k2".into()]).ids("a").query(); QueryBuilder::select().values(["k".into(), "k2".into()]).ids([1, 2]).query(); QueryBuilder::select().values(["k".into(), "k2".into()]).ids(QueryBuilder::search().from(1).query()).query(); +QueryBuilder::select().values(["k".into(), "k2".into()]).search().from(1).query(); // Equivalent to the previous query QueryBuilder::select().elements::().ids(1).query(); +QueryBuilder::select().elements::().ids(QueryBuilder::search().from("a").query()).query(); +QueryBuilder::select().elements::().search().from("a").query(); // Equivalent to the previous query ``` diff --git a/examples/app_db/src/main.rs b/examples/app_db/src/main.rs index d0eeb1e6d..55c88dc0b 100644 --- a/examples/app_db/src/main.rs +++ b/examples/app_db/src/main.rs @@ -55,23 +55,19 @@ fn main() -> Result<(), QueryError> { // SELECT * FROM users WHERE name = "user1" // ``` // - // It uses the `agdb::UserValue::db_keys()` to select required keys. It also - // changes the sarch algorithm to depth-first (default is breadth-first) + // It changes the search algorithm to depth-first (default is breadth-first) // which is more efficient when searching for a single item only. We could additionally // limit the search by adding `limit(1)` to ensure we get only one result back // and/or additional condition on `distance(Equal(2))` to stop search beyond users. But since // we know the structure of our data (graph) we can safely omit them as unnecessary here. let user_result = db.exec( QueryBuilder::select() - .ids( - QueryBuilder::search() - .depth_first() - .from("users") - .where_() - .key("username") - .value(Comparison::Equal("user1".into())) - .query(), - ) + .search() + .depth_first() + .from("users") + .where_() + .key("username") + .value(Comparison::Equal("user1".into())) .query(), )?; diff --git a/examples/indexes/src/main.rs b/examples/indexes/src/main.rs index 00a149d24..0d1c9cc21 100644 --- a/examples/indexes/src/main.rs +++ b/examples/indexes/src/main.rs @@ -58,12 +58,9 @@ fn main() -> Result<(), QueryError> { .exec( QueryBuilder::select() .values(User::db_keys()) - .ids( - QueryBuilder::search() - .index("username") - .value("user50") - .query(), - ) + .search() + .index("username") + .value("user50") .query(), )? .try_into()?; diff --git a/examples/joins/src/main.rs b/examples/joins/src/main.rs index fe2643166..1406bd702 100644 --- a/examples/joins/src/main.rs +++ b/examples/joins/src/main.rs @@ -48,16 +48,13 @@ fn main() -> Result<(), QueryError> { let mut user_dbs: Vec = vec![]; db.exec( QueryBuilder::select() - .ids( - QueryBuilder::search() - .depth_first() - .from("user") - .where_() - .keys("role") - .or() - .keys("name") - .query(), - ) + .search() + .depth_first() + .from("user") + .where_() + .keys("role") + .or() + .keys("name") .query(), )? .elements @@ -87,15 +84,12 @@ fn main() -> Result<(), QueryError> { let user_dbs = db.transaction(|t| -> Result, QueryError> { let db_names = t.exec( QueryBuilder::select() - .ids( - QueryBuilder::search() - .from("user") - .where_() - .distance(CountComparison::Equal(2)) - .and() - .keys("name") - .query(), - ) + .search() + .from("user") + .where_() + .distance(CountComparison::Equal(2)) + .and() + .keys("name") .query(), )?; @@ -104,14 +98,11 @@ fn main() -> Result<(), QueryError> { for db_name in db_names.elements { let role = t.exec( QueryBuilder::select() - .ids( - QueryBuilder::search() - .to(db_name.id) - .limit(1) - .where_() - .keys("role") - .query(), - ) + .search() + .to(db_name.id) + .limit(1) + .where_() + .keys("role") .query(), )?; diff --git a/examples/schema_migration/src/main.rs b/examples/schema_migration/src/main.rs index 8cebd4251..1d9920cc6 100644 --- a/examples/schema_migration/src/main.rs +++ b/examples/schema_migration/src/main.rs @@ -110,13 +110,10 @@ fn main() -> Result<(), QueryError> { let users: Vec = t .exec( QueryBuilder::select() - .ids( - QueryBuilder::search() - .from("users") - .where_() - .distance(CountComparison::Equal(2)) - .query(), - ) + .search() + .from("users") + .where_() + .distance(CountComparison::Equal(2)) .query(), )? .try_into()?; diff --git a/examples/server_client_rust/src/main.rs b/examples/server_client_rust/src/main.rs index 32b361960..bf4201b14 100644 --- a/examples/server_client_rust/src/main.rs +++ b/examples/server_client_rust/src/main.rs @@ -60,15 +60,12 @@ async fn main() -> Result<(), anyhow::Error> { .query() .into(), QueryBuilder::select() - .ids( - QueryBuilder::search() - .depth_first() - .from("users") - .where_() - .key("username") - .value(Comparison::Equal("user1".into())) - .query(), - ) + .search() + .depth_first() + .from("users") + .where_() + .key("username") + .value(Comparison::Equal("user1".into())) .query() .into(), ]; diff --git a/examples/strong_types/src/main.rs b/examples/strong_types/src/main.rs index 73f427b8c..61467b5ed 100644 --- a/examples/strong_types/src/main.rs +++ b/examples/strong_types/src/main.rs @@ -1,7 +1,6 @@ use agdb::Comparison; use agdb::DbError; use agdb::DbMemory; -use agdb::DbUserValue; use agdb::DbValue; use agdb::QueryBuilder; use agdb::QueryError; @@ -106,10 +105,10 @@ fn main() -> Result<(), QueryError> { // SELECT username, password, status FROM users WHERE name = "user1" // ``` // - // It uses the `agdb::UserValue::db_keys()` to select required keys. It also - // changes the sarch algorithm to depth-first (default is breadth-first) - // which is more efficient when searching for a single item only. We could additionally - // limit the search by adding `limit(1)` to ensure we get only one result back + // Internally it uses the `agdb::DbUserValue::db_keys()` to select required keys as the `User` is + // required to implement the `DbUserValue` trait. It also changes the sarch algorithm to depth-first + // (default is breadth-first) which is more efficient when searching for a single item only. We could + // additionally limit the search by adding `limit(1)` to ensure we get only one result back // and/or additional condition on `distance(Equal(2))` to stop search beyond users. But since // we know the structure of our data (graph) we can safely omit them as unnecessary here. // @@ -118,16 +117,13 @@ fn main() -> Result<(), QueryError> { let user: User = db .exec( QueryBuilder::select() - .values(User::db_keys()) - .ids( - QueryBuilder::search() - .depth_first() - .from("users") - .where_() - .key("username") - .value(Comparison::Equal("user1".into())) - .query(), - ) + .elements::() + .search() + .depth_first() + .from("users") + .where_() + .key("username") + .value(Comparison::Equal("user1".into())) .query(), )? .try_into()?;