Initial commit

This commit is contained in:
2026-04-17 23:26:01 +00:00
commit 2ea4ca5d52
409 changed files with 63459 additions and 0 deletions

View File

@@ -0,0 +1,158 @@
---
title: Use getFirstListItem for Single Record Lookups
impact: MEDIUM
impactDescription: Cleaner code, automatic error handling for not found
tags: query, lookup, find, getFirstListItem
---
## Use getFirstListItem for Single Record Lookups
Use `getFirstListItem()` when you need to find a single record by a field value other than ID. It's cleaner than `getList()` with limit 1 and provides proper error handling.
**Incorrect (manual single-record lookup):**
```javascript
// Using getList with limit 1 - verbose
async function findUserByEmail(email) {
const result = await pb.collection('users').getList(1, 1, {
filter: pb.filter('email = {:email}', { email })
});
if (result.items.length === 0) {
throw new Error('User not found');
}
return result.items[0];
}
// Using getFullList then filtering - wasteful
async function findUserByUsername(username) {
const users = await pb.collection('users').getFullList({
filter: pb.filter('username = {:username}', { username })
});
return users[0]; // Might be undefined!
}
// Fetching by ID when you have a different identifier
async function findProductBySku(sku) {
// Wrong: getOne expects the record ID
const product = await pb.collection('products').getOne(sku); // Fails!
}
```
**Correct (using getFirstListItem):**
```javascript
// Clean single-record lookup by any field
async function findUserByEmail(email) {
try {
const user = await pb.collection('users').getFirstListItem(
pb.filter('email = {:email}', { email })
);
return user;
} catch (error) {
if (error.status === 404) {
return null; // Not found
}
throw error;
}
}
// Lookup by unique field
async function findProductBySku(sku) {
return pb.collection('products').getFirstListItem(
pb.filter('sku = {:sku}', { sku })
);
}
// Lookup with expand
async function findOrderByNumber(orderNumber) {
return pb.collection('orders').getFirstListItem(
pb.filter('orderNumber = {:num}', { num: orderNumber }),
{ expand: 'customer,items' }
);
}
// Complex filter conditions
async function findActiveSubscription(userId) {
return pb.collection('subscriptions').getFirstListItem(
pb.filter(
'user = {:userId} && status = "active" && expiresAt > @now',
{ userId }
)
);
}
// With field selection
async function getUserIdByEmail(email) {
const user = await pb.collection('users').getFirstListItem(
pb.filter('email = {:email}', { email }),
{ fields: 'id' }
);
return user.id;
}
```
**Comparison with getOne:**
```javascript
// getOne - fetch by record ID
const post = await pb.collection('posts').getOne('abc123');
// getFirstListItem - fetch by any filter (use pb.filter for safe binding)
const post = await pb.collection('posts').getFirstListItem(
pb.filter('slug = {:slug}', { slug: 'hello-world' })
);
const user = await pb.collection('users').getFirstListItem(
pb.filter('username = {:name}', { name: 'john' })
);
const order = await pb.collection('orders').getFirstListItem(
pb.filter('orderNumber = {:num}', { num: 12345 })
);
```
**Error handling:**
```javascript
// getFirstListItem throws 404 if no match found
try {
const user = await pb.collection('users').getFirstListItem(
pb.filter('email = {:email}', { email })
);
return user;
} catch (error) {
if (error.status === 404) {
// No matching record - handle appropriately
return null;
}
// Other error (network, auth, etc.)
throw error;
}
// Wrapper function for optional lookup
async function findFirst(collection, filter, options = {}) {
try {
return await pb.collection(collection).getFirstListItem(filter, options);
} catch (error) {
if (error.status === 404) return null;
throw error;
}
}
// Usage
const user = await findFirst('users', pb.filter('email = {:e}', { e: email }));
if (!user) {
console.log('User not found');
}
```
**When to use each method:**
| Method | Use When |
|--------|----------|
| `getOne(id)` | You have the record ID |
| `getFirstListItem(filter)` | Finding by unique field (email, slug, sku) |
| `getList(1, 1, { filter })` | Need pagination metadata |
| `getFullList({ filter })` | Expecting multiple results |
Reference: [PocketBase Records API](https://pocketbase.io/docs/api-records/)