# Saving data

> Keep coins, levels, warnings and settings after a command ends.

Variables in your code are gone when the command ends. To keep something, save it. There are three ways:

| Way | Good for | Kept after restart |
|---|---|---|
| Server and member variables | One value: a counter, a setting, a user's coins | Yes |
| Mongo database | Lists and records: inventories, warnings, leaderboards | Yes |
| Temp variables | Short-lived values | No |

**Start with member variables** for simple things. **Move to Mongo** when you need lists, many fields per user, or sorting.

## Server variables

One value for the whole server.

```python
count = int(server_var("counter", 0))
update_server_var("counter", count + 1)
set_content(f"This command was used {count + 1} times.")
```

- `server_var(name, default)` reads a value. Gives `default` when it was never saved.
- `update_server_var(name, value)` saves a value.

You can see and edit saved values on the dashboard under **Variables**.

## Member variables

One value per member. Without `member=`, it is the person who ran the command.

```python
coins = int(member_var("coins", 0))
update_member_var("coins", coins + 100)
set_content(f"You now have {coins + 100} coins.")
```

For someone else, pass `member=`:

```python
their_coins = int(member_var("coins", 0, member=target))
```

> **Values come back as text:** Saved values are stored as text. `member_var("coins")` gives `"100"`, not `100`. Wrap it in `int(...)` before doing sums.

## Mongo databases

A Mongo database stores records. A record is a set of named fields, like a row:

```python
{"user_id": 123, "coins": 500, "items": ["sword", "shield"]}
```

Open one with `SlashMongo(database, collection)`. Pick any names. Each server gets its own private copy.

```python
db = SlashMongo("economy", "wallets")

wallet = await db.find_one({"user_id": user.id})
coins = wallet["coins"] if wallet else 0

await db.update_one(
    {"user_id": user.id},
    {"$set": {"coins": coins + 100}},
    upsert=True,
)
```

`upsert=True` makes the record when it does not exist yet.

### Common actions

| Code | What it does |
|---|---|
| `await db.insert_one(record)` | Add one record. |
| `await db.find_one(filter)` | Get the first match, or `None`. |
| `await db.find(filter)` | Get all matches, as a list. |
| `await db.update_one(filter, changes)` | Change the first match. |
| `await db.delete_one(filter)` | Delete the first match. |
| `await db.count(filter)` | Count matches. |

Write `await` in front of every Mongo call.

### Top 10 leaderboard

```python
db = SlashMongo("economy", "wallets")
top = await db.aggregate([
    {"$sort": {"coins": -1}},
    {"$limit": 10},
])
lines = [f"<@{w['user_id']}>: {w['coins']}" for w in top]
set_content(listify(lines, prefix="number"))
```

You can browse your data on the dashboard under **Mongo Databases**.

## Databases

**Databases** (under **Variables**) are tables you set up on the dashboard first, with fixed columns. Open one by its ID:

```python
db = await load_database("my_table_id")
rows = db.find(where={"user_id": str(user.id)})
await db.insert({"user_id": str(user.id), "note": "hello"})
```

Use these when you want to manage the rows by hand on the dashboard. For data that code writes, Mongo is easier.

## Temp variables

Kept in memory only. They vanish when the bot restarts.

```python
set_temp_var("last_winner", user.id)
winner = temp_var("last_winner")
```

Use them for short-lived values where losing them does not matter.

## Locks

Two people can run a command at the same time. When both change the same record, one change can be lost. Wrap the change in a lock:

```python
acquire_lock(f"wallet-{user.id}", error="Slow down, try again.")
# ... read, change, save ...
release_lock(f"wallet-{user.id}")
```

> **Always release the lock:** A lock is not released when the command ends. If your code stops with an error between the two lines, the lock stays on and the command keeps saying "Slow down". Keep the code between them short and safe, or release the lock before any `set_error`.

Full list: [Storage reference](https://ccbot.app/docs/reference/storage).
