Skip to content

Commit 222bb46

Browse files
authored
Merge pull request #2601 from appwrite/docs/databases-skip-totals
document skipping totals on list endpoints
2 parents a534d62 + 71f081c commit 222bb46

File tree

2 files changed

+332
-2
lines changed

2 files changed

+332
-2
lines changed

src/routes/docs/products/databases/pagination/+page.markdoc

Lines changed: 326 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,4 +294,329 @@ Using offset pagination on large tables and frequently updated tables may result
294294

295295
Cursor pagination should be used for frequently updated tablesDB.
296296
It is best suited for lazy-loaded pages with infinite scrolling.
297-
For example, a feed, comment section, chat history, or high volume datasets.
297+
For example, a feed, comment section, chat history, or high volume datasets.
298+
299+
# Skip totals for faster lists {% #skip-totals %}
300+
301+
By default, list responses include an accurate `total` count. On large tables and filtered queries, calculating totals requires an extra database COUNT which can add latency.
302+
303+
If your UI does not rely on exact totals (for example, infinite scroll or “load more”), you can skip counting totals by passing `total=false` to any list endpoint. The response keeps the same shape and sets `total` to `0` for compatibility.
304+
305+
Recommendations:
306+
- Use with cursor pagination for the best performance and UX.
307+
- Keep the default behavior when you need “N results” or “Page X of Y”.
308+
309+
{% multicode %}
310+
```client-web
311+
import { Client, Query, TablesDB } from "appwrite";
312+
313+
const client = new Client()
314+
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1')
315+
.setProject('<PROJECT_ID>');
316+
317+
const tablesDB = new TablesDB(client);
318+
319+
const page = await tablesDB.listRows({
320+
databaseId: '<DATABASE_ID>',
321+
tableId: '<TABLE_ID>',
322+
queries: [
323+
Query.limit(25)
324+
],
325+
total: false // Skip computing total count
326+
});
327+
```
328+
```server-nodejs
329+
const sdk = require('node-appwrite');
330+
331+
const client = new sdk.Client()
332+
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1')
333+
.setProject('<PROJECT_ID>')
334+
.setKey('<YOUR_API_KEY>');
335+
336+
const tablesDB = new sdk.TablesDB(client);
337+
338+
const page = await tablesDB.listRows({
339+
databaseId: '<DATABASE_ID>',
340+
tableId: '<TABLE_ID>',
341+
queries: [
342+
sdk.Query.limit(25)
343+
],
344+
total: false // Skip computing total count
345+
});
346+
```
347+
```server-python
348+
from appwrite.client import Client
349+
from appwrite.services.tables_db import TablesDB
350+
from appwrite.query import Query
351+
352+
client = Client()
353+
client.set_endpoint('https://<REGION>.cloud.appwrite.io/v1')
354+
client.set_project('<PROJECT_ID>')
355+
client.set_key('<YOUR_API_KEY>')
356+
357+
tables_db = TablesDB(client)
358+
359+
page = tables_db.list_rows(
360+
database_id='<DATABASE_ID>',
361+
table_id='<TABLE_ID>',
362+
queries=[
363+
Query.limit(25)
364+
],
365+
total=False # Skip computing total count
366+
)
367+
```
368+
```server-ruby
369+
require 'appwrite'
370+
371+
client = Appwrite::Client.new
372+
.set_endpoint('https://<REGION>.cloud.appwrite.io/v1')
373+
.set_project('<PROJECT_ID>')
374+
.set_key('<YOUR_API_KEY>')
375+
376+
tables_db = Appwrite::TablesDB.new(client)
377+
378+
page = tables_db.list_rows(
379+
database_id: '<DATABASE_ID>',
380+
table_id: '<TABLE_ID>',
381+
queries: [
382+
Appwrite::Query.limit(25)
383+
],
384+
total: false # Skip computing total count
385+
)
386+
```
387+
```server-deno
388+
import { Client, Query, TablesDB } from "https://deno.land/x/appwrite/mod.ts";
389+
390+
const client = new Client()
391+
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1')
392+
.setProject('<PROJECT_ID>')
393+
.setKey('<YOUR_API_KEY>');
394+
395+
const tablesDB = new TablesDB(client);
396+
397+
const page = await tablesDB.listRows({
398+
databaseId: '<DATABASE_ID>',
399+
tableId: '<TABLE_ID>',
400+
queries: [
401+
Query.limit(25)
402+
],
403+
total: false // Skip computing total count
404+
});
405+
```
406+
```server-php
407+
<?php
408+
409+
use Appwrite\Client;
410+
use Appwrite\Query;
411+
use Appwrite\Services\TablesDB;
412+
413+
$client = (new Client())
414+
->setEndpoint('https://<REGION>.cloud.appwrite.io/v1')
415+
->setProject('<PROJECT_ID>')
416+
->setKey('<YOUR_API_KEY>');
417+
418+
$tablesDB = new TablesDB($client);
419+
420+
$page = $tablesDB->listRows(
421+
databaseId: '<DATABASE_ID>',
422+
tableId: '<TABLE_ID>',
423+
queries: [
424+
Query::limit(25)
425+
],
426+
total: false // Skip computing total count
427+
);
428+
```
429+
```server-go
430+
package main
431+
432+
import (
433+
"fmt"
434+
"github.com/appwrite/sdk-for-go/appwrite"
435+
"github.com/appwrite/sdk-for-go/query"
436+
)
437+
438+
func main() {
439+
client := appwrite.NewClient()
440+
client.SetEndpoint("https://<REGION>.cloud.appwrite.io/v1")
441+
client.SetProject("<PROJECT_ID>")
442+
client.SetKey("<YOUR_API_KEY>")
443+
444+
tablesDB := appwrite.NewTablesDB(client)
445+
446+
page, err := tablesDB.ListRows(
447+
"<DATABASE_ID>",
448+
"<TABLE_ID>",
449+
appwrite.WithListRowsQueries([]string{
450+
query.Limit(25)
451+
}),
452+
appwrite.WithListRowsTotal(false), // Skip computing total count
453+
)
454+
455+
if err != nil {
456+
fmt.Println(err)
457+
}
458+
}
459+
```
460+
```server-swift
461+
import Appwrite
462+
import AppwriteModels
463+
464+
func main() async throws {
465+
let client = Client()
466+
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1")
467+
.setProject("<PROJECT_ID>")
468+
.setKey("<YOUR_API_KEY>")
469+
470+
let tablesDB = TablesDB(client)
471+
472+
let page = try await tablesDB.listRows(
473+
databaseId: "<DATABASE_ID>",
474+
tableId: "<TABLE_ID>",
475+
queries: [
476+
Query.limit(25)
477+
],
478+
total: false // Skip computing total count
479+
)
480+
}
481+
```
482+
```server-kotlin
483+
import io.appwrite.Client
484+
import io.appwrite.Query
485+
import io.appwrite.services.TablesDB
486+
487+
suspend fun main() {
488+
val client = Client(applicationContext)
489+
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1")
490+
.setProject("<PROJECT_ID>")
491+
.setKey("<YOUR_API_KEY>")
492+
493+
val tablesDB = TablesDB(client)
494+
495+
val page = tablesDB.listRows(
496+
databaseId = "<DATABASE_ID>",
497+
tableId = "<TABLE_ID>",
498+
queries = listOf(
499+
Query.limit(25)
500+
),
501+
total = false // Skip computing total count
502+
)
503+
}
504+
```
505+
```server-java
506+
import io.appwrite.Client;
507+
import io.appwrite.Query;
508+
import io.appwrite.services.TablesDB;
509+
510+
public class Main {
511+
public static void main(String[] args) throws Exception {
512+
Client client = new Client()
513+
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1")
514+
.setProject("<PROJECT_ID>")
515+
.setKey("<YOUR_API_KEY>");
516+
517+
TablesDB tablesDB = new TablesDB(client);
518+
519+
RowList page = tablesDB.listRows(
520+
"<DATABASE_ID>",
521+
"<TABLE_ID>",
522+
Arrays.asList(
523+
Query.limit(25)
524+
),
525+
false // Skip computing total count
526+
);
527+
}
528+
}
529+
```
530+
```client-flutter
531+
import 'package:appwrite/appwrite.dart';
532+
533+
void main() async {
534+
final client = Client()
535+
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1')
536+
.setProject('<PROJECT_ID>');
537+
538+
final tablesDB = TablesDB(client);
539+
540+
final page = await tablesDB.listRows(
541+
databaseId: '<DATABASE_ID>',
542+
tableId: '<TABLE_ID>',
543+
queries: [
544+
Query.limit(25)
545+
],
546+
total: false, // Skip computing total count
547+
);
548+
}
549+
```
550+
```client-apple
551+
import Appwrite
552+
import AppwriteModels
553+
554+
func main() async throws {
555+
let client = Client()
556+
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1")
557+
.setProject("<PROJECT_ID>")
558+
559+
let tablesDB = TablesDB(client)
560+
561+
let page = try await tablesDB.listRows(
562+
databaseId: "<DATABASE_ID>",
563+
tableId: "<TABLE_ID>",
564+
queries: [
565+
Query.limit(25)
566+
],
567+
total: false // Skip computing total count
568+
)
569+
}
570+
```
571+
```client-android-kotlin
572+
import io.appwrite.Client
573+
import io.appwrite.Query
574+
import io.appwrite.services.TablesDB
575+
576+
suspend fun main() {
577+
val client = Client(applicationContext)
578+
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1")
579+
.setProject("<PROJECT_ID>")
580+
581+
val tablesDB = TablesDB(client)
582+
583+
val page = tablesDB.listRows(
584+
databaseId = "<DATABASE_ID>",
585+
tableId = "<TABLE_ID>",
586+
queries = listOf(
587+
Query.limit(25)
588+
),
589+
total = false // Skip computing total count
590+
)
591+
}
592+
```
593+
```graphql
594+
query {
595+
tablesListRows(
596+
databaseId: "<DATABASE_ID>",
597+
tableId: "<TABLE_ID>",
598+
queries: ["limit(25)"],
599+
total: false
600+
) {
601+
total
602+
rows {
603+
_id
604+
data
605+
}
606+
}
607+
}
608+
```
609+
```http
610+
GET /v1/tablesdb/<DATABASE_ID>/tables/<TABLE_ID>/rows?total=false HTTP/1.1
611+
Content-Type: application/json
612+
X-Appwrite-Project: <PROJECT_ID>
613+
```
614+
```json
615+
{
616+
"total": 0,
617+
"rows": [
618+
{ "_id": "...", "data": { /* ... */ } }
619+
]
620+
}
621+
```
622+
{% /multicode %}

src/routes/docs/products/databases/rows/+page.markdoc

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,14 +135,19 @@ You must grant _read_ permissions to users at the _table level_ before users can
135135
[Learn more about permissions](#permissions)
136136
{% /info %}
137137

138-
Rows can be retrieved using the [List Row](/docs/references/cloud/client-web/tables#listRows) endpoint.
138+
Rows can be retrieved using the [List rows](/docs/references/cloud/client-web/tables#listRows) endpoint.
139139

140140
Results can be filtered, sorted, and paginated using Appwrite's shared set of query methods.
141141
You can find a full guide on querying in the [Queries Guide](/docs/products/databases/queries).
142142

143143
By default, results are limited to the _first 25 items_.
144144
You can change this through [pagination](/docs/products/databases/pagination).
145145

146+
{% info title="Speed up lists by skipping totals" %}
147+
If your UI doesn't need an exact total, set the `total` flag to `false` on list calls. The response keeps the same shape and sets `total` to `0`.
148+
This reduces latency for large tables and filtered queries. Learn more in [Pagination: Skip totals](/docs/products/databases/pagination#skip-totals).
149+
{% /info %}
150+
146151
{% multicode %}
147152
```client-web
148153
import { Client, Query, TablesDB } from "appwrite";

0 commit comments

Comments
 (0)