The MemberExpand system allows you to selectively fetch only the data you need when retrieving member information. This reduces payload size, improves response times, and minimizes network bandwidth usage.
By default, member fetches return only core fields. Use field expansion to include additional information like contact details, employment, marital status, and discipleship data.
// ❌ Without field expansion: ~5KB per member (all fields)let member = try await congregation.members.fetch(id: memberId)// ✅ With field expansion: ~1KB per member (only contact info)let member = try await congregation.members.fetch( id: memberId, expanded: [.contactInformation])// For 1000 members:// Without expansion: ~5MB total// With expansion: ~1MB total (80% reduction!)
The MemberExpand enum defines which related information to include:
public enum MemberExpand: String, Codable, Sendable { /// Expand employment information case employmentInformation /// Expand contact information case contactInformation /// Expand marital information case martialInformation /// Expand discipleship and spiritual information case discipleshipInformation}
Use the fetchAll(pageNumber:pageSize:expanded:) method for paginated results with expansion:
// Fetch 100 members with contact and discipleship infolet response = try await congregation.members.fetchAll( pageNumber: 1, pageSize: 100, expanded: [.contactInformation, .discipleshipInformation])print("Total members: \(response.totalSize)")print("Fetched: \(response.members.count) members")for member in response.members { // Contact info is available if let email = member.contactInformation?.email { print("\(member.memberName ?? "Unknown"): \(email)") } // Discipleship info is available if let baptized = member.discipleshipInformation?.waterBaptism?.received { print(" Baptized: \(baptized)") }}
// ✅ Good: Only expand fields you'll uselet member = try await congregation.members.fetch( id: memberId, expanded: [.contactInformation] // Just need email/phone)// ❌ Bad: Expanding everything when you only need contact infolet member = try await congregation.members.fetch( id: memberId, expanded: [ .contactInformation, .employmentInformation, .martialInformation, .discipleshipInformation ])
Cache fully expanded member data to avoid repeated fetches:
actor MemberCache { private var cache: [String: Member] = [:] func getMember(id: MemberID, congregation: CongregationKit) async throws -> Member { if let cached = cache[id.rawValue] { return cached } // Fetch with full expansion and cache let member = try await congregation.members.fetch( id: id, expanded: [ .contactInformation, .employmentInformation, .martialInformation, .discipleshipInformation ] ) cache[id.rawValue] = member return member }}