You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MongoDB Stitch iOS(Swift):如何通过skip实现分页?

Answer

Great question! I’ve dealt with this exact issue when building pagination with MongoDB Stitch on iOS using Swift, so I can help break this down for you.

First, you’re absolutely right: the RemoteFindOptions in the Stitch iOS SDK doesn’t include a direct skip parameter. This isn’t an oversight though—MongoDB actually recommends keyset pagination (cursor-based pagination) over traditional skip/limit for better performance, especially with large datasets (since skip forces the database to scan and discard all the skipped documents, which gets slow as the page number increases).

This approach relies on filtering documents based on the last item from the previous page, paired with a stable sort order. Here’s how to implement it:

  1. Choose a stable sort field: Use a unique, ordered field like _id (MongoDB’s built-in unique ID, which is time-ordered) or a custom field like createdAt.
  2. Fetch the first page: Use limit to get your page size, then store the last document’s sort field value.
  3. Fetch subsequent pages: Add a filter to only retrieve documents that come after (or before, depending on sort direction) the last item from the previous page, then apply the same limit.

Swift Code Example

Suppose we’re paginating a Posts collection sorted by createdAt in descending order:

// Track the last document's createdAt value from the previous page
private var lastPageEndDate: Date?

// Fetch the first page of posts
func fetchFirstPage() {
    guard let client = Stitch.defaultAppClient?.serviceClient(
        fromFactory: remoteMongoClientFactory,
        withName: "mongodb-atlas"
    ) else { return }
    
    let postsCollection = client.db("your-database-name").collection("Posts")
    let findOptions = RemoteFindOptions(
        sort: ["createdAt": -1], // Sort newest to oldest
        limit: 20 // 20 items per page
    )
    
    postsCollection.find([], options: findOptions) { result in
        switch result {
        case .success(let documents):
            // Update the last page's end date with the last document's createdAt
            self.lastPageEndDate = documents.last?["createdAt"] as? Date
            // Handle your post data here
        case .failure(let error):
            print("Failed to fetch first page: \(error.localizedDescription)")
        }
    }
}

// Fetch the next page of posts
func fetchNextPage() {
    guard let lastDate = lastPageEndDate,
          let client = Stitch.defaultAppClient?.serviceClient(
              fromFactory: remoteMongoClientFactory,
              withName: "mongodb-atlas"
          ) else { return }
    
    let postsCollection = client.db("your-database-name").collection("Posts")
    // Filter for posts older than the last one from the previous page (since we're sorting descending)
    let paginationFilter: Document = ["createdAt": ["$lt": lastDate]]
    let findOptions = RemoteFindOptions(
        sort: ["createdAt": -1],
        limit: 20
    )
    
    postsCollection.find(paginationFilter, options: findOptions) { result in
        switch result {
        case .success(let documents):
            if let lastDoc = documents.last {
                self.lastPageEndDate = lastDoc["createdAt"] as? Date
            } else {
                // No more pages left
                self.lastPageEndDate = nil
            }
            // Handle your post data here
        case .failure(let error):
            print("Failed to fetch next page: \(error.localizedDescription)")
        }
    }
}

Option 2: Use a Stitch Function for skip (If You Must)

If you absolutely need to use skip (e.g., for a small dataset where performance isn’t a concern), you can create a Stitch Server Function that supports the skip parameter, then call that function from your iOS app.

Step 1: Create the Stitch Function

In your MongoDB Stitch dashboard, add a new function with this code:

exports = function(skipAmount, pageLimit) {
    const db = context.services.get("mongodb-atlas").db("your-database-name");
    const postsCollection = db.collection("Posts");
    // Use skip and limit directly in the query
    return postsCollection.find({})
        .sort({ createdAt: -1 })
        .skip(skipAmount)
        .limit(pageLimit)
        .toArray();
};

Step 2: Call the Function from iOS

func fetchPageWithSkip(skip: Int, limit: Int) {
    guard let stitchClient = Stitch.defaultAppClient else { return }
    
    stitchClient.callFunction(
        withName: "fetchPaginatedPosts", // Match your function name from Stitch
        arguments: [skip, limit]
    ) { result in
        switch result {
        case .success(let documents):
            // Handle the returned paginated documents
        case .failure(let error):
            print("Failed to call pagination function: \(error.localizedDescription)")
        }
    }
}

Final Notes

  • Stick with cursor-based pagination whenever possible—it’s faster, more reliable, and avoids issues with duplicate/missing documents if data changes between pages.
  • The skip approach works but isn’t recommended for large datasets due to performance overhead.

内容的提问来源于stack exchange,提问作者Koh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 15:07:57