Skip to main content
POST
/
{collection}
/
count
Count Documents
curl --request POST \
  --url https://api.example.com/{collection}/count \
  --header 'Content-Type: application/json' \
  --data '{
  "filter": {}
}'
{
  "data": {
    "count": 123
  },
  "error": {
    "code": "<string>",
    "message": "<string>",
    "details": {}
  }
}

Overview

The count endpoint returns the number of documents in a collection that match a given filter query. The count respects RBAC permissions and only includes documents the authenticated user has permission to read.

Request

collection
string
required
The name of the collection to count documents in
filter
object
MongoDB-style filter query to match documents. If omitted, counts all documents the user has permission to read.

Count All Documents Example

POST /users/count
No request body needed to count all accessible documents.

Count with Filter Example

{
  "filter": {
    "status": "active",
    "department": "Engineering"
  }
}

Complex Filter Example

{
  "filter": {
    "created_at": {
      "$gte": "2024-01-01T00:00:00Z",
      "$lt": "2024-12-31T23:59:59Z"
    },
    "age": { "$gte": 18 },
    "role": { "$in": ["developer", "designer", "manager"] },
    "email_verified": true
  }
}

Response

data
object
count
integer
The number of documents matching the filter criteria that the user has permission to read

Response Example

{
  "data": {
    "count": 142
  }
}

Filter Query Syntax

The filter parameter supports MongoDB query operators:

Comparison Operators

{
  "filter": {
    "age": { "$gte": 18, "$lt": 65 },
    "salary": { "$gt": 50000 },
    "status": { "$ne": "deleted" }
  }
}
  • $eq: Equal to
  • $ne: Not equal to
  • $gt: Greater than
  • $gte: Greater than or equal to
  • $lt: Less than
  • $lte: Less than or equal to

Array Operators

{
  "filter": {
    "role": { "$in": ["admin", "moderator"] },
    "status": { "$nin": ["banned", "suspended"] }
  }
}
  • $in: Value is in array
  • $nin: Value is not in array

Logical Operators

{
  "filter": {
    "$or": [
      { "status": "active" },
      { "last_login": { "$gte": "2024-01-01T00:00:00Z" } }
    ],
    "department": { "$exists": true }
  }
}
  • $and: All conditions must match
  • $or: At least one condition must match
  • $not: Inverts the condition
  • $exists: Field exists/doesn’t exist

Pattern Matching

{
  "filter": {
    "email": { "$regex": "@company\\.com$" }
  }
}

RBAC Enforcement

From handlers_query.go:470-477: The count operation automatically combines the provided filter with RBAC query filters. This ensures users only count documents they have permission to read.
rbacFilter := h.getRBACQueryFilter(authCtx, collection, schema.ActionRead)
combinedFilter := h.combineFilters(request.Filter, rbacFilter)
For example:
  • A manager might only count documents in their department
  • A user might only count their own documents
  • An admin might count all documents

Use Cases

Pre-validation Before Batch Operations

// Count documents before batch delete
POST /products/count
{
  "filter": {
    "status": "discontinued",
    "stock": 0
  }
}

// Response: { "data": { "count": 47 } }
// Now you know 47 documents will be deleted

Analytics and Reporting

// Count active users by department
POST /users/count
{
  "filter": {
    "status": "active",
    "department": "Engineering"
  }
}

Validation Before Updates

// Verify how many documents will be affected
POST /orders/count
{
  "filter": {
    "status": "pending",
    "created_at": { "$lt": "2024-01-01T00:00:00Z" }
  }
}

Performance Considerations

Count operations use MongoDB’s native count functionality, which is optimized for indexed fields. Ensure your filter uses indexed fields for best performance on large collections.

Optimization Tips

  1. Use indexed fields in your filter criteria
  2. Avoid complex regex patterns on non-indexed fields
  3. Consider collection size: Counts on very large collections may take time
  4. Cache results if the data doesn’t change frequently

Error Responses

error
object
code
string
Error code:
  • collection_not_found: Collection does not exist
  • forbidden: User lacks read permission
  • bad_request: Invalid filter syntax
  • internal_error: Database operation failed
message
string
Human-readable error message
details
object
Additional error context

Error Example

{
  "error": {
    "code": "bad_request",
    "message": "Invalid JSON body",
    "details": {
      "error": "unexpected end of JSON input"
    }
  }
}

Audit Logging

All count operations are logged to the audit trail with:
  • User ID and roles
  • Collection name
  • Filter criteria
  • Success/failure status
  • Timestamp
From handlers_query.go:492-493

Code Reference

Implementation: pkg/api/handlers_query.go:422-502

Build docs developers (and LLMs) love