mirror of
https://github.com/HeyPuter/puter.git
synced 2026-05-03 16:10:31 +00:00
* feat: add querying with prefix patterns example and documentation * refine --------- Co-authored-by: Reynaldi Chernando <reynaldichernando@gmail.com>
This commit is contained in:
@@ -232,6 +232,7 @@ You can see various Puter.js Key-Value Store features in action from the followi
|
||||
- [Decrement](/playground/kv-decr/)
|
||||
- [Delete](/playground/kv-del/)
|
||||
- [List](/playground/kv-list/)
|
||||
- [Querying with Prefix Patterns](/playground/kv-prefix-patterns/)
|
||||
- [Flush](/playground/kv-flush/)
|
||||
- [Expire](/playground/kv-expire/)
|
||||
- [Expire At](/playground/kv-expireAt/)
|
||||
|
||||
@@ -6,6 +6,8 @@ platforms: [websites, apps, nodejs, workers]
|
||||
|
||||
Returns an array of all keys in the user's key-value store for the current app. If the user has no keys, the array will be empty.
|
||||
|
||||
Because filtering is prefix-based, `list()` works best when you design keys around the read patterns your app needs. In practice, that means your key naming convention becomes your query plan.
|
||||
|
||||
Results are sorted lexicographically (string order) by key.
|
||||
|
||||
## Syntax
|
||||
@@ -193,3 +195,70 @@ If the user has no keys, the array will be empty.
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
<strong class="example-title">Design keys for query-like filtering with prefix patterns</strong>
|
||||
|
||||
```html;kv-prefix-patterns
|
||||
<html>
|
||||
<body>
|
||||
<script src="https://js.puter.com/v2/"></script>
|
||||
<script>
|
||||
(async () => {
|
||||
const orders = [
|
||||
{ id: '0001', status: 'pending', customer: 'alice', total: 48 },
|
||||
{ id: '0002', status: 'shipped', customer: 'alice', total: 72 },
|
||||
{ id: '0003', status: 'pending', customer: 'bob', total: 15 },
|
||||
];
|
||||
|
||||
// In KV, key design is your query plan.
|
||||
// We store the same order under multiple prefixes so each read path
|
||||
// becomes a simple prefix query with puter.kv.list().
|
||||
for (const order of orders) {
|
||||
await puter.kv.set(`demo:order:by-id:${order.id}`, order);
|
||||
await puter.kv.set(`demo:order:by-status:${order.status}:${order.id}`, order);
|
||||
await puter.kv.set(`demo:order:by-customer:${order.customer}:${order.id}`, order);
|
||||
await puter.kv.set(`demo:order:by-status-customer:${order.status}:${order.customer}:${order.id}`, order);
|
||||
}
|
||||
|
||||
puter.print('<b>Stored read paths</b><br>');
|
||||
puter.print('demo:order:by-status:pending:*<br>');
|
||||
puter.print('demo:order:by-customer:alice:*<br>');
|
||||
puter.print('demo:order:by-status-customer:pending:alice:*<br><br>');
|
||||
|
||||
const pendingOrders = await puter.kv.list('demo:order:by-status:pending:*', true);
|
||||
puter.print('<b>Query: status = pending</b><br>');
|
||||
pendingOrders.forEach(({ key, value }) => {
|
||||
puter.print(`${key} => ${value.customer} ($${value.total})<br>`);
|
||||
});
|
||||
puter.print('<br>');
|
||||
|
||||
const aliceOrders = await puter.kv.list('demo:order:by-customer:alice:*', true);
|
||||
puter.print('<b>Query: customer = alice</b><br>');
|
||||
aliceOrders.forEach(({ key, value }) => {
|
||||
puter.print(`${key} => ${value.status} ($${value.total})<br>`);
|
||||
});
|
||||
puter.print('<br>');
|
||||
|
||||
const alicePendingOrders = await puter.kv.list('demo:order:by-status-customer:pending:alice:*', true);
|
||||
puter.print('<b>Query: status = pending AND customer = alice</b><br>');
|
||||
alicePendingOrders.forEach(({ key, value }) => {
|
||||
puter.print(`${key} => order ${value.id} ($${value.total})<br>`);
|
||||
});
|
||||
puter.print('<br>');
|
||||
|
||||
puter.print('<b>Takeaway</b><br>');
|
||||
puter.print('With puter.kv.list(), filtering comes from key prefixes.<br>');
|
||||
puter.print('If you need another query path, add another prefix-friendly key.<br><br>');
|
||||
|
||||
// Cleanup
|
||||
for (const order of orders) {
|
||||
await puter.kv.del(`demo:order:by-id:${order.id}`);
|
||||
await puter.kv.del(`demo:order:by-status:${order.status}:${order.id}`);
|
||||
await puter.kv.del(`demo:order:by-customer:${order.customer}:${order.id}`);
|
||||
await puter.kv.del(`demo:order:by-status-customer:${order.status}:${order.customer}:${order.id}`);
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
@@ -418,13 +418,19 @@ const examples = [
|
||||
description: 'See how keys are returned in lexicographic order with puter.kv.list(). Run and modify this example in the playground.',
|
||||
slug: 'kv-list-sort',
|
||||
source: '/playground/examples/kv-list-sort.html',
|
||||
},
|
||||
{
|
||||
},
|
||||
{
|
||||
title: 'List (Zero-Padding)',
|
||||
description: 'Learn how to sort numeric keys correctly by zero-padding. Run and experiment with this example in the playground.',
|
||||
slug: 'kv-list-padding',
|
||||
source: '/playground/examples/kv-list-padding.html',
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'List (Prefix Patterns)',
|
||||
description: 'Learn how to model SQL-style filtering in Puter.js KV by designing keys for prefix queries. Run and modify this example in the playground.',
|
||||
slug: 'kv-prefix-patterns',
|
||||
source: '/playground/examples/kv-prefix-patterns.html',
|
||||
},
|
||||
{
|
||||
title: 'Flush',
|
||||
description: 'Clear all data with Puter.js key-value API. Run and experiment with this flush example in the playground.',
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
<html>
|
||||
<body>
|
||||
<script src="https://js.puter.com/v2/"></script>
|
||||
<script>
|
||||
(async () => {
|
||||
const orders = [
|
||||
{ id: '0001', status: 'pending', customer: 'alice', total: 48 },
|
||||
{ id: '0002', status: 'shipped', customer: 'alice', total: 72 },
|
||||
{ id: '0003', status: 'pending', customer: 'bob', total: 15 },
|
||||
];
|
||||
|
||||
// In KV, key design is your query plan.
|
||||
// We store the same order under multiple prefixes so each read path
|
||||
// becomes a simple prefix query with puter.kv.list().
|
||||
for (const order of orders) {
|
||||
await puter.kv.set(`demo:order:by-id:${order.id}`, order);
|
||||
await puter.kv.set(`demo:order:by-status:${order.status}:${order.id}`, order);
|
||||
await puter.kv.set(`demo:order:by-customer:${order.customer}:${order.id}`, order);
|
||||
await puter.kv.set(`demo:order:by-status-customer:${order.status}:${order.customer}:${order.id}`, order);
|
||||
}
|
||||
|
||||
puter.print('<b>Stored read paths</b><br>');
|
||||
puter.print('demo:order:by-status:pending:*<br>');
|
||||
puter.print('demo:order:by-customer:alice:*<br>');
|
||||
puter.print('demo:order:by-status-customer:pending:alice:*<br><br>');
|
||||
|
||||
const pendingOrders = await puter.kv.list('demo:order:by-status:pending:*', true);
|
||||
puter.print('<b>Query: status = pending</b><br>');
|
||||
pendingOrders.forEach(({ key, value }) => {
|
||||
puter.print(`${key} => ${value.customer} ($${value.total})<br>`);
|
||||
});
|
||||
puter.print('<br>');
|
||||
|
||||
const aliceOrders = await puter.kv.list('demo:order:by-customer:alice:*', true);
|
||||
puter.print('<b>Query: customer = alice</b><br>');
|
||||
aliceOrders.forEach(({ key, value }) => {
|
||||
puter.print(`${key} => ${value.status} ($${value.total})<br>`);
|
||||
});
|
||||
puter.print('<br>');
|
||||
|
||||
const alicePendingOrders = await puter.kv.list('demo:order:by-status-customer:pending:alice:*', true);
|
||||
puter.print('<b>Query: status = pending AND customer = alice</b><br>');
|
||||
alicePendingOrders.forEach(({ key, value }) => {
|
||||
puter.print(`${key} => order ${value.id} ($${value.total})<br>`);
|
||||
});
|
||||
puter.print('<br>');
|
||||
|
||||
puter.print('<b>Takeaway</b><br>');
|
||||
puter.print('With puter.kv.list(), filtering comes from key prefixes.<br>');
|
||||
puter.print('If you need another query path, add another prefix-friendly key.<br><br>');
|
||||
|
||||
// Cleanup
|
||||
for (const order of orders) {
|
||||
await puter.kv.del(`demo:order:by-id:${order.id}`);
|
||||
await puter.kv.del(`demo:order:by-status:${order.status}:${order.id}`);
|
||||
await puter.kv.del(`demo:order:by-customer:${order.customer}:${order.id}`);
|
||||
await puter.kv.del(`demo:order:by-status-customer:${order.status}:${order.customer}:${order.id}`);
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user