fn list_for
Similar to list_by
the list_for
option lets you query pages of entities.
The difference is that list_for
accepts an additional filter argument.
This is useful for situations where you have a 1-to-n
relationship between 2 entities and you want to find all entities on the n
side that share the same foreign key.
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 }, } impl IntoEvents<UserEvent> for NewUser { fn into_events(self) -> EntityEvents<UserEvent> { unimplemented!() } } impl TryFromEvents<UserEvent> for User { fn try_from_events(events: EntityEvents<UserEvent>) -> Result<Self, EsEntityError> { unimplemented!() } } pub struct NewUser { id: UserId, name: String } #[derive(EsEntity)] pub struct User { pub id: UserId, events: EntityEvents<UserEvent>, } use es_entity::*; es_entity::entity_id! { UserDocumentId } #[derive(EsEvent, Debug, Serialize, Deserialize)] #[serde(tag = "type", rename_all = "snake_case")] #[es_event(id = "UserDocumentId")] pub enum UserDocumentEvent { Initialized { id: UserDocumentId, owner_id: UserId }, } impl IntoEvents<UserDocumentEvent> for NewUserDocument { fn into_events(self) -> EntityEvents<UserDocumentEvent> { EntityEvents::init( self.id, [UserDocumentEvent::Initialized { id: self.id, owner_id: self.owner_id, }], ) } } impl TryFromEvents<UserDocumentEvent> for UserDocument { fn try_from_events(events: EntityEvents<UserDocumentEvent>) -> Result<Self, EsEntityError> { Ok(UserDocument { id: events.id().clone(), owner_id: UserId::new(), events }) } } pub struct NewUserDocument { id: UserDocumentId, owner_id: UserId } #[derive(EsEntity)] pub struct UserDocument { pub id: UserDocumentId, owner_id: UserId, events: EntityEvents<UserDocumentEvent>, } #[derive(EsRepo)] #[es_repo( entity = "UserDocument", columns( // The column name in the schema user_id( ty = "UserId", // generate the `list_for` fn list_for, // The accessor on the `NewUserDocument` type create(accessor = "owner_id"), // Its immutable - so no need to ever update it update(persist = false) ) ) )] pub struct UserDocuments { pool: sqlx::PgPool } 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 docs = UserDocuments { pool: init_pool().await? }; // Assume we have an existing user that we can get the id from let owner_id = UserId::new(); // Batch creating a few entities for illustration let new_docs = vec![ NewUserDocument { id: UserDocumentId::new(), owner_id }, NewUserDocument { id: UserDocumentId::new(), owner_id } ]; docs.create_all(new_docs).await?; // The fns have the form `list_for_<filter>_by_<cursor>` let docs = docs.list_for_user_id_by_created_at( owner_id, Default::default(), Default::default() ).await?; assert_eq!(docs.entities.len(), 2); Ok(()) }