# Records API ## Overview The Records API provides CRUD operations for collection records. It handles: - Creating records - Reading records (single or list) - Updating records - Deleting records - Batch operations - Real-time subscriptions ## Authentication Most record operations require authentication: ```javascript // Include JWT token in requests const token = pb.authStore.token; // Or use SDK which handles it automatically const pb = new PocketBase('http://127.0.0.1:8090'); ``` ## Create Record ### Create Single Record ```javascript const record = await pb.collection('posts').create({ title: 'My Post', content: 'Hello world!', author: pb.authStore.model.id, published: true }); // Returns full record with ID, timestamps, etc. console.log(record.id); console.log(record.created); console.log(record.updated); ``` ### Create with Files ```javascript const formData = new FormData(); formData.append('title', 'Post with Image'); formData.append('image', fileInput.files[0]); const record = await pb.collection('posts').create(formData); const imageUrl = pb.files.getURL(record, record.image); ``` ### Create with Relations ```javascript const post = await pb.collection('posts').create({ title: 'My Post', author: authorId, // User ID category: categoryId // Category ID }); ``` ## Read Records ### Get Single Record ```javascript const record = await pb.collection('posts').getOne('RECORD_ID'); // Get with expand const record = await pb.collection('posts').getOne('RECORD_ID', { expand: 'author,comments' }); ``` ### Get Multiple Records (List) ```javascript const records = await pb.collection('posts').getList(1, 50); // Returns: // { // page: 1, // perPage: 50, // totalItems: 100, // totalPages: 2, // items: [ ... array of records ... ] // } ``` ### Pagination ```javascript // Page 1 const page1 = await pb.collection('posts').getList(1, 50); // Page 2 const page2 = await pb.collection('posts').getList(2, 50); // Large perPage const all = await pb.collection('posts').getList(1, 200); // Get all records (use carefully) const allRecords = await pb.collection('posts').getFullList(); ``` ### Filtering ```javascript const records = await pb.collection('posts').getList(1, 50, { filter: 'status = "published"' }); // Multiple conditions const records = await pb.collection('posts').getList(1, 50, { filter: 'status = "published" && created >= "2024-01-01"' }); // With OR const records = await pb.collection('posts').getList(1, 50, { filter: 'category = "tech" || category = "programming"' }); // By relation field const records = await pb.collection('comments').getList(1, 50, { filter: 'expand.post.title ~ "PocketBase"' }); ``` ### Sorting ```javascript // Sort by created date descending const records = await pb.collection('posts').getList(1, 50, { sort: '-created' }); // Sort by title ascending const records = await pb.collection('posts').getList(1, 50, { sort: 'title' }); // Multiple fields const records = await pb.collection('posts').getList(1, 50, { sort: 'status,-created' // status ascending, then created descending }); ``` ### Field Selection ```javascript // Select specific fields const records = await pb.collection('posts').getList(1, 50, { fields: 'id,title,author,created' }); // Exclude large fields const records = await pb.collection('posts').getList(1, 50, { fields: 'id,title,author,created,-content' }); // Select with expand const records = await pb.collection('posts').getList(1, 50, { fields: 'id,title,expand.author.name' }); ``` ### Relation Expansion ```javascript // Expand single relation const posts = await pb.collection('posts').getList(1, 50, { expand: 'author' }); // Expand multiple relations const posts = await pb.collection('posts').getList(1, 50, { expand: 'author,comments' }); // Expand nested relations const comments = await pb.collection('comments').getList(1, 50, { expand: 'post.author' }); // Use expand in filters const posts = await pb.collection('posts').getList(1, 50, { expand: 'author', filter: 'expand.author.role = "admin"' }); ``` ### Cursor-Based Pagination (PocketBase 0.20+) ```javascript // First page const page1 = await pb.collection('posts').getList(1, 50, { sort: 'created' }); // Get cursor (last item's sort value) const cursor = page1.items[page1.items.length - 1].created; // Next page const page2 = await pb.collection('posts').getList(1, 50, { filter: `created < "${cursor}"`, sort: 'created' }); ``` ## Update Record ### Update Single Record ```javascript const updated = await pb.collection('posts').update('RECORD_ID', { title: 'Updated Title', status: 'published' }); // Returns updated record console.log(updated.title); console.log(updated.updated); ``` ### Update with Files ```javascript const formData = new FormData(); formData.append('title', 'Updated Post'); formData.append('image', newFile); // Replace image // or formData.append('image', null); // Remove image const updated = await pb.collection('posts').update('RECORD_ID', formData); ``` ### Update Relations ```javascript // Update relation const updated = await pb.collection('posts').update('RECORD_ID', { author: newAuthorId }); // Add to one-to-many relation const comment = await pb.collection('comments').create({ post: postId, content: 'New comment' }); // Update comment await pb.collection('comments').update(comment.id, { content: 'Updated comment' }); ``` ## Delete Record ```javascript // Delete single record await pb.collection('posts').delete('RECORD_ID'); // Returns true on success, throws on failure ``` ## Batch Operations ### Create Multiple Records ```javascript const records = await pb.collection('posts').createBatch([ { title: 'Post 1', content: 'Content 1' }, { title: 'Post 2', content: 'Content 2' } ]); console.log(records.length); // 2 ``` ### Update Multiple Records ```javascript const records = await pb.collection('posts').updateBatch([ { id: 'RECORD_ID_1', title: 'Updated Title 1' }, { id: 'RECORD_ID_2', title: 'Updated Title 2' } ]); ``` ### Delete Multiple Records ```javascript await pb.collection('posts').deleteBatch([ 'RECORD_ID_1', 'RECORD_ID_2', 'RECORD_ID_3' ]); ``` ## Real-time Subscriptions ### Subscribe to All Collection Changes ```javascript // Subscribe to all changes pb.collection('posts').subscribe('*', function (e) { console.log(e.action); // 'create', 'update', or 'delete' console.log(e.record); // Changed record if (e.action === 'create') { console.log('New post created:', e.record); } else if (e.action === 'update') { console.log('Post updated:', e.record); } else if (e.action === 'delete') { console.log('Post deleted:', e.record); } }); ``` ### Subscribe to Specific Record ```javascript // Subscribe to specific record pb.collection('posts').subscribe('RECORD_ID', function (e) { console.log('Record changed:', e.record); }); ``` ### Unsubscribe ```javascript // Unsubscribe from specific record pb.collection('posts').unsubscribe('RECORD_ID'); // Unsubscribe from all collection changes pb.collection('posts').unsubscribe(); // Unsubscribe from all collections pb.collections.unsubscribe(); ``` ### Real-time with React ```javascript import { useEffect, useState } from 'react'; function PostsList() { const [posts, setPosts] = useState([]); useEffect(() => { loadPosts(); // Subscribe to real-time updates pb.collection('posts').subscribe('*', function (e) { if (e.action === 'create') { setPosts(prev => [e.record, ...prev]); } else if (e.action === 'update') { setPosts(prev => prev.map(p => p.id === e.record.id ? e.record : p)); } else if (e.action === 'delete') { setPosts(prev => prev.filter(p => p.id !== e.record.id)); } }); return () => { pb.collection('posts').unsubscribe(); }; }, []); async function loadPosts() { const records = await pb.collection('posts').getList(1, 50, { expand: 'author' }); setPosts(records.items); } return (
By {post.expand?.author?.name}