Skip to main content

Query Posts

The social.plus SDK provides powerful post querying functionality that enables flexible content discovery and filtering. Query posts from communities, user feeds, or across the entire platform with customizable search criteria and real-time results.

Overview

Flexible Filtering

Filter by post type, target, deletion status, and custom criteria

Live Results

Query results are returned as live collections with real-time updates

Query Parameters

ParameterTypeDescriptionOptions
targetIdStringCommunity or user IDCommunity ID, User ID
targetTypeStringType of targetcommunity, user
typesArrayPost content typestext, image, video, file, poll, liveStream, custom
includeDeletedBooleanInclude deleted poststrue, false (default)
sortByStringSort orderlastCreated (default), firstCreated
feedTypeStringFeed type filterpublished, reviewing, declined
untilAtDateTimeTime boundary for pagination (local-only). Stops fetching and collecting posts beyond this datetime.See Time-Bounded Pagination

Basic Post Querying

import AmitySDK

class PostQueryManager {
    private let client: AmityClient
    
    init(client: AmityClient) {
        self.client = client
    }
    
    // Query community posts with basic filters
    func queryCommunityPosts(
        communityId: String,
        postTypes: [AmityPostDataType] = [],
        includeDeleted: Bool = false
    ) -> AmityCollection<AmityPost> {
        
        let repository = AmityPostRepository(client: client)
        let query = AmityPostQuery()
            .targetId(communityId)
            .targetType(.community)
            .sortBy(.lastCreated)
            .includeDeleted(includeDeleted)
        
        if !postTypes.isEmpty {
            query.types(postTypes)
        }
        
        return repository.getPosts(query: query)
    }
    
    // Query user feed posts
    func queryUserPosts(
        userId: String,
        sortBy: AmityPostQuerySortOption = .lastCreated
    ) -> AmityCollection<AmityPost> {
        
        let repository = AmityPostRepository(client: client)
        let query = AmityPostQuery()
            .targetId(userId)
            .targetType(.user)
            .sortBy(sortBy)
            .includeDeleted(false)
        
        return repository.getPosts(query: query)
    }
    
    // Advanced media gallery query
    func queryMediaGallery(
        targetId: String,
        targetType: AmityPostTargetType,
        mediaTypes: [AmityPostDataType] = [.image, .video]
    ) -> AmityCollection<AmityPost> {
        
        let repository = AmityPostRepository(client: client)
        let query = AmityPostQuery()
            .targetId(targetId)
            .targetType(targetType)
            .types(mediaTypes)
            .sortBy(.lastCreated)
            .includeDeleted(false)
        
        return repository.getPosts(query: query)
    }
    
    // Query posts with live observation
    func observePosts(
        communityId: String,
        onUpdate: @escaping ([AmityPost]) -> Void,
        onError: @escaping (Error) -> Void
    ) -> AmityNotificationToken {
        
        let collection = queryCommunityPosts(communityId: communityId)
        
        return collection.observe { result in
            switch result {
            case .success(let postsInfo):
                let posts = postsInfo.object
                print("Posts updated: \(posts.count) total")
                onUpdate(posts)
                
            case .failure(let error):
                print("Query error: \(error)")
                onError(error)
            }
        }
    }
    
    // Query with pagination
    func queryPostsWithPagination(
        communityId: String,
        pageSize: Int = 20
    ) -> AmityCollection<AmityPost> {
        
        let repository = AmityPostRepository(client: client)
        let query = AmityPostQuery()
            .targetId(communityId)
            .targetType(.community)
            .sortBy(.lastCreated)
            .limit(pageSize)
        
        return repository.getPosts(query: query)
    }
    
    // Query posts for moderation
    func queryPostsForModeration(
        communityId: String,
        feedType: AmityPostFeedType = .reviewing
    ) -> AmityCollection<AmityPost> {
        
        let repository = AmityPostRepository(client: client)
        let query = AmityPostQuery()
            .targetId(communityId)
            .targetType(.community)
            .feedType(feedType)
            .sortBy(.lastCreated)
            .includeDeleted(true)
        
        return repository.getPosts(query: query)
    }
}

Time-Bounded Pagination with untilAt

Platform Availability: The untilAt parameter is currently available on iOS and Android only. Web (TypeScript) support is under development.
The untilAt parameter enables time-bounded pagination for post queries. When provided, the SDK stops fetching and collecting posts beyond the specified datetime boundary. This is useful for building “catch-up” feeds, historical views, or snapshotted timelines.

How It Works

  • Local-only filteruntilAt is never sent to the backend. The SDK enforces the boundary locally.
  • Exclusive comparison — A post whose createdAt equals exactly untilAt is not included.
  • Automatic pagination stop — Once the boundary is reached, no further pages are fetched and hasNextPage becomes false.
  • Real-time filtering — New posts arriving via real-time events are also checked against the boundary before being added to the live collection.
Sort DirectionuntilAt Acts AsExcludes Posts Where
lastCreated (newest first)Lower boundcreatedAt < untilAt (older than boundary)
firstCreated (oldest first)Upper boundcreatedAt > untilAt (newer than boundary)

Usage Example

import AmitySDK

// Query community posts up to a specific point in time
let repository = AmityPostRepository(client: client)

// Example: Only show posts from the last 7 days
let oneWeekAgo = Calendar.current.date(byAdding: .day, value: -7, to: Date())!

let query = AmityPostQuery()
    .targetId("community-123")
    .targetType(.community)
    .sortBy(.lastCreated)
    .untilAt(oneWeekAgo)
    .includeDeleted(false)

let collection = repository.getPosts(query: query)

let token = collection.observe { result in
    switch result {
    case .success(let postsInfo):
        let posts = postsInfo.object
        // All posts will have createdAt >= oneWeekAgo
        print("Posts within time window: \(posts.count)")
        
    case .failure(let error):
        print("Query error: \(error)")
    }
}

Limitations

  • Maximum of 100 posts per page is still enforced by the backend.
  • untilAt does not affect posts already persisted in the local database — it only controls what appears in the live collection result.
  • When no untilAt is provided, pagination behaves normally with no time boundary.

Advanced Query Features

Filter posts by specific content types to create focused views:
  • Media Gallery: Query only image and video posts
  • Text Content: Retrieve text-only posts for text analysis
  • File Sharing: Focus on file attachment posts
  • Interactive Content: Filter polls and live streams
Control visibility of deleted content based on user permissions:
  • Standard Users: See only their own deleted posts
  • Moderators: View all soft-deleted posts in communities
  • Admins: Access complete deletion history
  • Audit Trails: Track content lifecycle for compliance
Query posts based on their review status:
  • Published: Live posts visible to all users
  • Reviewing: Posts pending moderation approval
  • Declined: Posts rejected by moderators
  • Mixed: Custom combinations for workflow management
Optimize query performance for large datasets:
  • Pagination: Load posts in manageable chunks
  • Lazy Loading: Fetch additional data on demand
  • Caching: Store frequently accessed queries
  • Indexing: Leverage server-side optimizations

Common Use Cases

Community Feed

Display all posts in a community with real-time updates and customizable filtering options.

User Profile

Show a user’s post history with privacy controls and content type filtering.

Media Gallery

Create image and video galleries by filtering posts with media attachments.

Content Moderation

Review pending posts and manage community content with moderation-specific queries.

Analytics Dashboard

Gather post data for engagement metrics and community insights.

Search Results

Implement advanced search functionality with multiple filter criteria.

Best Practices

  • Use specific post types instead of querying all types
  • Implement pagination for large result sets
  • Cache frequently accessed queries
  • Dispose of live collections when no longer needed
  • Show loading states during query execution
  • Implement pull-to-refresh for live collections
  • Provide empty states for no results
  • Use skeleton screens for better perceived performance
  • Handle network connectivity issues gracefully
  • Implement retry mechanisms for failed queries
  • Provide meaningful error messages to users
  • Log query errors for debugging purposes
  • Dispose of live collections when views are destroyed
  • Implement proper lifecycle management
  • Use weak references to prevent memory leaks
  • Monitor memory usage in production

Query Examples

Custom Post Types: For custom post types, use a namespace-like format (e.g., "my.customtype"). This ensures proper categorization and prevents conflicts with built-in types.
Performance Note: Querying large datasets without proper filtering can impact performance. Always use appropriate filters and pagination for optimal user experience.