CRUD Operations
Master the four fundamental database operations: Create, Read, Update, and Delete across all platforms.CRUD operations are the building blocks of any application. Cocobase makes
them simple, intuitive, and consistent across all languages.
Overview
Cocobase provides type-safe, efficient CRUD operations for all supported platforms:- Create - Add new documents to collections
- Read - Retrieve documents by ID or with filters
- Update - Modify existing documents (partial or full)
- Delete - Remove documents from collections
- Batch Operations - Perform multiple operations at once
Create Documents
Add new documents to your collections with automatic ID generation and timestamp tracking.Basic Creation
- JavaScript
- TypeScript
- Dart
- Go
- Python
- HTTP
Copy
import { Cocobase } from 'cocobase';
const db = new Cocobase({ apiKey: 'your-api-key' });
// Create a single document
const user = await db.createDocument('users', {
name: 'John Doe',
email: '[email protected]',
age: 30,
active: true
});
console.log('Created user:', user.id);
Copy
import { Cocobase } from 'cocobase';
interface User {
name: string;
email: string;
age: number;
active: boolean;
}
const db = new Cocobase({ apiKey: 'your-api-key' });
// Type-safe document creation
const user = await db.createDocument<User>('users', {
name: 'John Doe',
email: '[email protected]',
age: 30,
active: true
});
console.log('Created user:', user.id);
// user.data is typed as User
Copy
import 'package:cocobase_flutter/cocobase_flutter.dart';
class User {
final String name;
final String email;
final int age;
final bool active;
User({
required this.name,
required this.email,
required this.age,
required this.active,
});
factory User.fromJson(Map<String, dynamic> json) => User(
name: json['name'],
email: json['email'],
age: json['age'],
active: json['active'],
);
Map<String, dynamic> toJson() => {
'name': name,
'email': email,
'age': age,
'active': active,
};
}
final db = Cocobase(CocobaseConfig(apiKey: 'your-api-key'));
// Type-safe document creation
final user = await db.createDocument<User>(
'users',
User(
name: 'John Doe',
email: '[email protected]',
age: 30,
active: true,
).toJson(),
converter: User.fromJson,
);
print('Created user: ${user.id}');
// user.data is typed as User
Copy
package main
import (
"context"
"fmt"
"log"
"github.com/lordace-coder/cocobase-go/cocobase"
)
func main() {
client := cocobase.NewClient(cocobase.Config{
APIKey: "your-api-key",
})
ctx := context.Background()
// Create a single document
data := map[string]interface{}{
"name": "John Doe",
"email": "[email protected]",
"age": 30,
"active": true,
}
doc, err := client.CreateDocument(ctx, "users", data)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Created user: %s\n", doc.ID)
}
Copy
from cocobase import Cocobase
db = Cocobase(api_key='your-api-key')
# Create a single document
user = db.create_document('users', {
'name': 'John Doe',
'email': '[email protected]',
'age': 30,
'active': True
})
print(f"Created user: {user['id']}")
Copy
curl -X POST https://api.cocobase.buzz/collections/users/documents \
-H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"name": "John Doe",
"email": "[email protected]",
"age": 30,
"active": true
}'
Type-Safe Creation
- JavaScript
- Dart
- Go
- Python
- HTTP
Copy
interface User {
name: string;
email: string;
age: number;
active: boolean;
}
const user = await db.createDocument<User>('users', {
name: 'Jane Smith',
email: '[email protected]',
age: 28,
active: true
});
// TypeScript knows the structure
console.log(user.data.name); // ✓ Type-safe
Copy
class User {
final String name;
final String email;
final int age;
final bool active;
User({
required this.name,
required this.email,
required this.age,
required this.active,
});
factory User.fromJson(Map<String, dynamic> json) {
return User(
name: json['name'],
email: json['email'],
age: json['age'],
active: json['active'],
);
}
Map<String, dynamic> toJson() => {
'name': name,
'email': email,
'age': age,
'active': active,
};
}
final user = await db.createDocument<User>(
'users',
User(
name: 'Jane Smith',
email: '[email protected]',
age: 28,
active: true,
).toJson(),
converter: User.fromJson,
);
print('Created: ${user.data.name}');
Copy
type User struct {
Name string `json:"name"`
Email string `json:"email"`
Age int `json:"age"`
Active bool `json:"active"`
}
data := map[string]interface{}{
"name": "Jane Smith",
"email": "[email protected]",
"age": 28,
"active": true,
}
doc, err := client.CreateDocument(ctx, "users", data)
if err != nil {
log.Fatal(err)
}
// Type assertion
if name, ok := doc.Data["name"].(string); ok {
fmt.Printf("Created: %s\n", name)
}
Copy
from typing import TypedDict
from cocobase import Cocobase
class User(TypedDict):
name: str
email: str
age: int
active: bool
db = Cocobase(api_key='your-api-key')
user_data: User = {
'name': 'Jane Smith',
'email': '[email protected]',
'age': 28,
'active': True
}
user = db.create_document('users', user_data)
print(f"Created: {user['data']['name']}")
Copy
# HTTP requests are inherently untyped
# Use JSON schema validation if needed
curl -X POST https://api.cocobase.buzz/collections/users/documents \
-H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"name": "Jane Smith",
"email": "[email protected]",
"age": 28,
"active": true
}'
Batch Creation
Create multiple documents in a single operation for better performance.- JavaScript
- Dart
- Go
- Python
- HTTP
Copy
const users = await db.createDocuments('users', [
{ name: 'Alice', email: '[email protected]', age: 25 },
{ name: 'Bob', email: '[email protected]', age: 32 },
{ name: 'Charlie', email: '[email protected]', age: 28 }
]);
console.log(`Created ${users.length} users`);
Copy
final users = [
{'name': 'Alice', 'email': '[email protected]', 'age': 25},
{'name': 'Bob', 'email': '[email protected]', 'age': 32},
{'name': 'Charlie', 'email': '[email protected]', 'age': 28},
];
for (var userData in users) {
await db.createDocument('users', userData);
}
Copy
// Batch creation via API
users := []map[string]interface{}{
{"name": "Alice", "email": "[email protected]", "age": 25},
{"name": "Bob", "email": "[email protected]", "age": 32},
{"name": "Charlie", "email": "[email protected]", "age": 28},
}
for _, userData := range users {
_, err := client.CreateDocument(ctx, "users", userData)
if err != nil {
log.Printf("Error creating user: %v\n", err)
}
}
Copy
users = [
{'name': 'Alice', 'email': '[email protected]', 'age': 25},
{'name': 'Bob', 'email': '[email protected]', 'age': 32},
{'name': 'Charlie', 'email': '[email protected]', 'age': 28}
]
# Create documents individually
for user_data in users:
db.create_document('users', user_data)
print(f"Created {len(users)} users")
Copy
curl -X POST https://api.cocobase.buzz/collections/users/batch/documents \
-H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"documents": [
{"name": "Alice", "email": "[email protected]", "age": 25},
{"name": "Bob", "email": "[email protected]", "age": 32},
{"name": "Charlie", "email": "[email protected]", "age": 28}
]
}'
Read Documents
Retrieve documents by ID, or query collections with filters and pagination.Get Single Document
- JavaScript
- Dart
- Go
- Python
- HTTP
Copy
const user = await db.getDocument('users', 'user-123');
console.log(user.data);
Copy
final user = await db.getDocument('users', 'user-123');
print('User: ${user.data}');
Copy
doc, err := client.GetDocument(ctx, "users", "user-123")
if err != nil {
if apiErr, ok := err.(*cocobase.APIError); ok {
if apiErr.StatusCode == 404 {
fmt.Println("Document not found")
return
}
}
log.Fatal(err)
}
fmt.Printf("User: %+v\n", doc.Data)
Copy
user = db.get_document('users', 'user-123')
print(f"User: {user['data']}")
Copy
curl https://api.cocobase.buzz/collections/users/documents/user-123 \
-H "X-API-Key: your-api-key"
List All Documents
- JavaScript
- Dart
- Go
- Python
- HTTP
Copy
const allUsers = await db.listDocuments('users');
console.log(`Total users: ${allUsers.length}`);
Copy
final allUsers = await db.listDocuments('users');
print('Total users: ${allUsers.length}');
Copy
docs, err := client.ListDocuments(ctx, "users", nil)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Total users: %d\n", len(docs))
Copy
all_users = db.list_documents('users')
print(f"Total users: {len(all_users)}")
Copy
curl https://api.cocobase.buzz/collections/users/documents \
-H "X-API-Key: your-api-key"
With Filters
- JavaScript
- Dart
- Go
- Python
- HTTP
Copy
// Get active users
const activeUsers = await db.listDocuments('users', {
filters: { active: true }
});
// Get users older than 25
const olderUsers = await db.listDocuments('users', {
filters: { age_gte: 25 }
});
// Multiple filters (AND logic)
const specificUsers = await db.listDocuments('users', {
filters: {
active: true,
age_gte: 25,
age_lte: 40
}
});
Copy
// Get active users
final activeUsers = await db.listDocuments('users', filters: {
'active': true,
});
// Get users older than 25
final olderUsers = await db.listDocuments('users', filters: {
'age__gte': 25,
});
// Multiple filters (AND logic)
final specificUsers = await db.listDocuments('users', filters: {
'active': true,
'age__gte': 25,
'age__lte': 40,
});
Copy
// Get active users
query := cocobase.NewQuery().Where("active", true)
activeUsers, err := client.ListDocuments(ctx, "users", query)
// Get users older than 25
query = cocobase.NewQuery().GreaterThanOrEqual("age", 25)
olderUsers, err := client.ListDocuments(ctx, "users", query)
// Multiple filters (AND logic)
query = cocobase.NewQuery().
Where("active", true).
GreaterThanOrEqual("age", 25).
LessThanOrEqual("age", 40)
specificUsers, err := client.ListDocuments(ctx, "users", query)
Copy
# Get active users
active_users = db.list_documents('users', filters={
'active': True
})
# Get users older than 25
older_users = db.list_documents('users', filters={
'age__gte': 25
})
# Multiple filters (AND logic)
specific_users = db.list_documents('users', filters={
'active': True,
'age__gte': 25,
'age__lte': 40
})
Copy
# Get active users
curl "https://api.cocobase.buzz/collections/users/documents?active=true" \
-H "X-API-Key: your-api-key"
# Get users older than 25
curl "https://api.cocobase.buzz/collections/users/documents?age_gte=25" \
-H "X-API-Key: your-api-key"
# Multiple filters (AND logic)
curl "https://api.cocobase.buzz/collections/users/documents?active=true&age_gte=25&age_lte=40" \
-H "X-API-Key: your-api-key"
With Pagination
- JavaScript
- Dart
- Go
- Python
- HTTP
Copy
// Get first page (10 users)
const page1 = await db.listDocuments('users', {
limit: 10,
offset: 0
});
// Get second page
const page2 = await db.listDocuments('users', {
limit: 10,
offset: 10
});
// Helper function
function getPage(pageNumber, pageSize = 10) {
return db.listDocuments('users', {
limit: pageSize,
offset: (pageNumber - 1) * pageSize
});
}
const page3 = await getPage(3); // Users 21-30
Copy
// Get first page (10 users)
final page1 = await db.listDocuments('users', filters: {
'limit': 10,
'offset': 0,
});
// Get second page
final page2 = await db.listDocuments('users', filters: {
'limit': 10,
'offset': 10,
});
// Using QueryBuilder
final page3 = await db.listDocuments(
'users',
queryBuilder: QueryBuilder().limit(10).offset(20),
);
Copy
// Get first page (10 users)
query := cocobase.NewQuery().Limit(10).Offset(0)
page1, err := client.ListDocuments(ctx, "users", query)
// Get second page
query = cocobase.NewQuery().Limit(10).Offset(10)
page2, err := client.ListDocuments(ctx, "users", query)
// Helper function
func getPage(client *cocobase.Client, page, perPage int) ([]cocobase.Document, error) {
query := cocobase.NewQuery().
Limit(perPage).
Offset((page - 1) * perPage)
return client.ListDocuments(ctx, "users", query)
}
page3, err := getPage(client, 3, 10) // Users 21-30
Copy
# Get first page (10 users)
page1 = db.list_documents('users', filters={
'limit': 10,
'offset': 0
})
# Get second page
page2 = db.list_documents('users', filters={
'limit': 10,
'offset': 10
})
# Helper function
def get_page(page_number, page_size=10):
return db.list_documents('users', filters={
'limit': page_size,
'offset': (page_number - 1) * page_size
})
page3 = get_page(3) # Users 21-30
Copy
# Get first page (10 users)
curl "https://api.cocobase.buzz/collections/users/documents?limit=10&offset=0" \
-H "X-API-Key: your-api-key"
# Get second page
curl "https://api.cocobase.buzz/collections/users/documents?limit=10&offset=10" \
-H "X-API-Key: your-api-key"
# Get page 3
curl "https://api.cocobase.buzz/collections/users/documents?limit=10&offset=20" \
-H "X-API-Key: your-api-key"
Update Documents
Modify existing documents with partial or full updates.Basic Update
- JavaScript
- Dart
- Go
- Python
- HTTP
Copy
await db.updateDocument('users', 'user-123', {
age: 31,
active: false
});
console.log('User updated');
Copy
await db.updateDocument('users', 'user-123', {
'age': 31,
'active': false,
});
print('User updated');
Copy
updates := map[string]interface{}{
"age": 31,
"active": false,
}
doc, err := client.UpdateDocument(ctx, "users", "user-123", updates)
if err != nil {
log.Fatal(err)
}
fmt.Println("User updated")
Copy
db.update_document('users', 'user-123', {
'age': 31,
'active': False
})
print("User updated")
Copy
curl -X PATCH https://api.cocobase.buzz/collections/users/documents/user-123 \
-H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"age": 31,
"active": false
}'
Updates are partial by default - you only need to provide the fields you
want to change. Other fields remain unchanged.
Batch Update
- JavaScript
- Dart
- Go
- Python
- HTTP
Copy
// Update multiple documents at once
await db.updateDocuments('users', {
'user-1': { age: 31 },
'user-2': { age: 29 },
'user-3': { active: false }
});
Copy
// Update documents individually
final updates = {
'user-1': {'age': 31},
'user-2': {'age': 29},
'user-3': {'active': false},
};
for (var entry in updates.entries) {
await db.updateDocument('users', entry.key, entry.value);
}
Copy
// Update documents individually
updates := map[string]map[string]interface{}{
"user-1": {"age": 31},
"user-2": {"age": 29},
"user-3": {"active": false},
}
for docID, data := range updates {
_, err := client.UpdateDocument(ctx, "users", docID, data)
if err != nil {
log.Printf("Failed to update %s: %v\n", docID, err)
}
}
Copy
# Update documents individually
updates = {
'user-1': {'age': 31},
'user-2': {'age': 29},
'user-3': {'active': False}
}
for doc_id, data in updates.items():
db.update_document('users', doc_id, data)
Copy
curl -X POST https://api.cocobase.buzz/collections/users/batch/documents/update \
-H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"updates": {
"user-1": {"data": {"age": 31}},
"user-2": {"data": {"age": 29}},
"user-3": {"data": {"active": false}}
}
}'
Delete Documents
Remove documents from collections permanently.Delete Single Document
- JavaScript
- Dart
- Go
- Python
- HTTP
Copy
await db.deleteDocument('users', 'user-123');
console.log('User deleted');
Copy
await db.deleteDocument('users', 'user-123');
print('User deleted');
Copy
err := client.DeleteDocument(ctx, "users", "user-123")
if err != nil {
log.Fatal(err)
}
fmt.Println("User deleted")
Copy
db.delete_document('users', 'user-123')
print("User deleted")
Copy
curl -X DELETE https://api.cocobase.buzz/collections/users/documents/user-123 \
-H "X-API-Key: your-api-key"
Batch Delete
- JavaScript
- Dart
- Go
- Python
- HTTP
Copy
const idsToDelete = ['user-1', 'user-2', 'user-3'];
const result = await db.deleteDocuments('users', idsToDelete);
console.log(`Deleted ${result.count} documents`);
Copy
final idsToDelete = ['user-1', 'user-2', 'user-3'];
for (var id in idsToDelete) {
await db.deleteDocument('users', id);
}
print('Deleted ${idsToDelete.length} documents');
Copy
idsToDelete := []string{"user-1", "user-2", "user-3"}
for _, id := range idsToDelete {
err := client.DeleteDocument(ctx, "users", id)
if err != nil {
log.Printf("Failed to delete %s: %v\n", id, err)
}
}
Copy
ids_to_delete = ['user-1', 'user-2', 'user-3']
for doc_id in ids_to_delete:
db.delete_document('users', doc_id)
print(f"Deleted {len(ids_to_delete)} documents")
Copy
curl -X POST https://api.cocobase.buzz/collections/users/batch/documents/delete \
-H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"document_ids": ["user-1", "user-2", "user-3"]
}'
Soft Delete (Recommended)
Instead of permanently deleting, mark documents as deleted for recovery options.- JavaScript
- Dart
- Go
- Python
- HTTP
Copy
// Mark as deleted instead of removing
await db.updateDocument('users', 'user-123', {
deleted: true,
deletedAt: new Date().toISOString()
});
// Query non-deleted items
const activeUsers = await db.listDocuments('users', {
filters: { deleted: false }
});
Copy
// Mark as deleted
await db.updateDocument('users', 'user-123', {
'deleted': true,
'deletedAt': DateTime.now().toIso8601String(),
});
// Query non-deleted items
final activeUsers = await db.listDocuments('users', filters: {
'deleted': false,
});
Copy
// Mark as deleted
updates := map[string]interface{}{
"deleted": true,
"deletedAt": time.Now().Format(time.RFC3339),
}
_, err := client.UpdateDocument(ctx, "users", "user-123", updates)
// Query non-deleted items
query := cocobase.NewQuery().Where("deleted", false)
activeUsers, err := client.ListDocuments(ctx, "users", query)
Copy
from datetime import datetime
# Mark as deleted
db.update_document('users', 'user-123', {
'deleted': True,
'deletedAt': datetime.utcnow().isoformat()
})
# Query non-deleted items
active_users = db.list_documents('users', filters={
'deleted': False
})
Copy
# Mark as deleted
curl -X PATCH https://api.cocobase.buzz/collections/users/documents/user-123 \
-H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"deleted": true,
"deletedAt": "2024-01-15T10:30:00Z"
}'
# Query non-deleted items
curl "https://api.cocobase.buzz/collections/users/documents?deleted=false" \
-H "X-API-Key: your-api-key"
Error Handling
Handle errors gracefully across all operations.- JavaScript
- Dart
- Go
- Python
- HTTP
Copy
try {
const user = await db.getDocument('users', userId);
console.log(user);
} catch (error) {
console.error('Failed to fetch user:', error.message);
// Handle error appropriately
}
Copy
try {
final user = await db.getDocument('users', userId);
print(user);
} on DioException catch (e) {
if (e.response?.statusCode == 404) {
print('Document not found');
} else {
print('Network error: ${e.message}');
}
} catch (e) {
print('Unexpected error: $e');
}
Copy
doc, err := client.GetDocument(ctx, "users", userID)
if err != nil {
if apiErr, ok := err.(*cocobase.APIError); ok {
switch apiErr.StatusCode {
case 404:
fmt.Println("Document not found")
case 401:
fmt.Println("Not authenticated")
case 403:
fmt.Println("Permission denied")
default:
fmt.Printf("Error: %s\n", apiErr.Suggestion)
}
} else {
log.Fatal(err)
}
}
Copy
try:
user = db.get_document('users', user_id)
print(user)
except Exception as e:
if '404' in str(e):
print("Document not found")
else:
print(f"Failed to fetch user: {e}")
Copy
# Check HTTP status codes
# 200 OK - Success
# 404 Not Found - Document doesn't exist
# 401 Unauthorized - Invalid API key
# 403 Forbidden - Permission denied
# 500 Internal Server Error - Server error
Best Practices
1. Use Type Safety
1. Use Type Safety
Define your data structures for better development experience and fewer bugs.
Copy
// ✓ Good: Type-safe
interface User {
name: string;
email: string;
}
const user = await db.createDocument<User>('users', {
name: 'John',
email: '[email protected]'
});
2. Handle Errors
2. Handle Errors
Always wrap operations in try-catch blocks or check for errors.
Copy
// ✓ Good: Error handling
try {
const user = await db.getDocument('users', userId);
console.log(user);
} catch (error) {
console.error('Failed to fetch user:', error.message);
}
3. Use Batch Operations
3. Use Batch Operations
Batch operations are more efficient than multiple individual requests.
Copy
// ✓ Good: Single batch operation
await db.createDocuments('users', [user1, user2, user3]);
// ✗ Bad: Multiple individual operations
await db.createDocument('users', user1);
await db.createDocument('users', user2);
await db.createDocument('users', user3);
4. Prefer Soft Deletes
4. Prefer Soft Deletes
Use soft deletes for important data to enable recovery.
Copy
// ✓ Good: Soft delete
await db.updateDocument('users', userId, {
deleted: true,
deletedAt: new Date().toISOString()
});
5. Add Timestamps
5. Add Timestamps
Track when records are created and modified.
Copy
// ✓ Good: Include timestamps
const post = await db.createDocument('posts', {
title: 'My Post',
content: '...',
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString()
});
