fn list_by
To load a whole page of entities at once you can set the list_by option on the column.
This will generate the list_by_<column> fns and appropriate cursor structs.
extern crate es_entity;
extern crate sqlx;
extern crate serde;
extern crate tokio;
extern crate anyhow;
extern crate uuid;
use serde::{Deserialize, Serialize};
es_entity::entity_id! { UserId }
#[derive(EsEvent, Debug, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
#[es_event(id = "UserId")]
pub enum UserEvent {
Initialized { id: UserId, name: String },
NameUpdated { name: String },
Deleted
}
impl IntoEvents<UserEvent> for NewUser {
fn into_events(self) -> EntityEvents<UserEvent> {
EntityEvents::init(
self.id,
[UserEvent::Initialized {
id: self.id,
name: self.name,
}],
)
}
}
impl TryFromEvents<UserEvent> for User {
fn try_from_events(events: EntityEvents<UserEvent>) -> Result<Self, EsEntityError> {
Ok(User { id: events.id().clone(), name: "Fred".to_string(), events })
}
}
pub struct NewUser { id: UserId, name: String }
#[derive(EsEntity)]
pub struct User {
pub id: UserId,
name: String,
events: EntityEvents<UserEvent>,
}
use es_entity::*;
#[derive(EsRepo)]
#[es_repo(
entity = "User",
// list_by will generate the UsersByNameCursor
columns(name(ty = "String", list_by))
)]
pub struct Users {
pool: sqlx::PgPool
}
// // Generated code:
// pub mod user_cursor {
// pub struct UsersByNameCursor {
// name: String
// // id is always added to disambiguate
// // incase the `name` column is not unique
// id: UserId,
// }
//
// // Cursors that always exist:
// pub struct UsersById {
// id: UserId,
// }
//
// pub struct UsersByCreatedAt {
// created_at: chrono::DateTime<chrono::Utc>
// id: UserId,
// }
// }
//
async fn init_pool() -> anyhow::Result<sqlx::PgPool> {
let pg_con = format!("postgres://user:password@localhost:5432/pg");
Ok(sqlx::PgPool::connect(&pg_con).await?)
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let users = Users { pool: init_pool().await? };
let new_user = NewUser { id: UserId::new(), name: "Fred".to_string() };
users.create(new_user).await?;
let PaginatedQueryRet {
entities,
has_next_page: _,
end_cursor: _,
} = users
.list_by_id(
PaginatedQueryArgs {
first: 5,
// after: None represents beginning of the list
after: Some(user_cursor::UsersByIdCursor {
id: uuid::Uuid::nil().into(),
}),
},
ListDirection::Ascending,
)
.await?;
assert!(!entities.is_empty());
// To collect all entities in a loop you can use `into_next_query()`.
// This is not recommended - just to highlight the API.
let mut query = Default::default();
let mut all_users = Vec::new();
loop {
let mut res = users.list_by_name(query, Default::default()).await?;
all_users.extend(res.entities.drain(..));
if let Some(next_query) = res.into_next_query() {
query = next_query;
} else {
break;
}
}
assert!(!all_users.is_empty());
Ok(())
}