> ## Documentation Index
> Fetch the complete documentation index at: https://clickhouse.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# 如何查询 S3 存储桶中的数据

> 了解如何使用 chDB 查询 S3 存储桶中的数据。

全球有大量数据存储在亚马逊 S3 存储桶中。
在本指南中，我们将学习如何使用 chDB 查询这些数据。

<div id="setup">
  ## 环境准备
</div>

先创建一个虚拟环境：

```bash theme={null}
python -m venv .venv
source .venv/bin/activate
```

现在我们来安装 chDB。
请确保版本为 2.0.2 或更高：

```bash theme={null}
pip install "chdb>=2.0.2"
```

接下来，我们来安装 IPython：

```bash theme={null}
pip install ipython
```

我们将使用 `ipython` 运行本指南后续部分中的命令，你可以通过运行以下命令启动它：

```bash theme={null}
ipython
```

你也可以在 Python 脚本或你常用的 notebook 中使用这段代码。

<div id="listing-files-in-an-s3-bucket">
  ## 列出 S3 存储桶中的文件
</div>

我们先列出[包含亚马逊评论的 S3 存储桶](/docs/zh/get-started/sample-datasets/amazon-reviews)中的所有文件。
为此，我们可以使用 [`s3` 表函数](/docs/zh/reference/functions/table-functions/s3)，并传入文件路径或一组文件的通配符。

<Tip>
  如果只传入 bucket 名称，就会抛出异常。
</Tip>

我们还会使用 [`One`](/docs/zh/reference/formats/One) 输入格式，这样就不会解析文件；而是每个文件返回一行，我们可以通过 `_file` 虚拟列访问文件，并通过 `_path` 虚拟列访问路径。

```python theme={null}
import chdb

chdb.query("""
SELECT
    _file,
    _path
FROM s3('s3://datasets-documentation/amazon_reviews/*.parquet', One)
SETTINGS output_format_pretty_row_numbers=0
""", 'PrettyCompact')
```

```text theme={null}
┌─_file───────────────────────────────┬─_path─────────────────────────────────────────────────────────────────────┐
│ amazon_reviews_2010.snappy.parquet  │ datasets-documentation/amazon_reviews/amazon_reviews_2010.snappy.parquet  │
│ amazon_reviews_1990s.snappy.parquet │ datasets-documentation/amazon_reviews/amazon_reviews_1990s.snappy.parquet │
│ amazon_reviews_2013.snappy.parquet  │ datasets-documentation/amazon_reviews/amazon_reviews_2013.snappy.parquet  │
│ amazon_reviews_2015.snappy.parquet  │ datasets-documentation/amazon_reviews/amazon_reviews_2015.snappy.parquet  │
│ amazon_reviews_2014.snappy.parquet  │ datasets-documentation/amazon_reviews/amazon_reviews_2014.snappy.parquet  │
│ amazon_reviews_2012.snappy.parquet  │ datasets-documentation/amazon_reviews/amazon_reviews_2012.snappy.parquet  │
│ amazon_reviews_2000s.snappy.parquet │ datasets-documentation/amazon_reviews/amazon_reviews_2000s.snappy.parquet │
│ amazon_reviews_2011.snappy.parquet  │ datasets-documentation/amazon_reviews/amazon_reviews_2011.snappy.parquet  │
└─────────────────────────────────────┴───────────────────────────────────────────────────────────────────────────┘
```

该存储桶中只有 Parquet 文件。

<div id="querying-files-in-an-s3-bucket">
  ## 查询 S3 存储桶中的文件
</div>

接下来，我们来看看如何查询这些文件。
如果想统计这些文件中各个文件的行数，可以运行以下查询：

```python theme={null}
chdb.query("""
SELECT
    _file,
    count() AS count,
    formatReadableQuantity(count) AS readableCount    
FROM s3('s3://datasets-documentation/amazon_reviews/*.parquet')
GROUP BY ALL
SETTINGS output_format_pretty_row_numbers=0
""", 'PrettyCompact')
```

```text theme={null}
┌─_file───────────────────────────────┬────count─┬─readableCount───┐
│ amazon_reviews_2013.snappy.parquet  │ 28034255 │ 28.03 million   │
│ amazon_reviews_1990s.snappy.parquet │   639532 │ 639.53 thousand │
│ amazon_reviews_2011.snappy.parquet  │  6112495 │ 6.11 million    │
│ amazon_reviews_2015.snappy.parquet  │ 41905631 │ 41.91 million   │
│ amazon_reviews_2012.snappy.parquet  │ 11541011 │ 11.54 million   │
│ amazon_reviews_2000s.snappy.parquet │ 14728295 │ 14.73 million   │
│ amazon_reviews_2014.snappy.parquet  │ 44127569 │ 44.13 million   │
│ amazon_reviews_2010.snappy.parquet  │  3868472 │ 3.87 million    │
└─────────────────────────────────────┴──────────┴─────────────────┘
```

我们也可以传入 S3 存储桶的 HTTP URI，得到相同的结果：

```python theme={null}
chdb.query("""
SELECT
    _file,
    count() AS count,
    formatReadableQuantity(count) AS readableCount    
FROM s3('https://datasets-documentation.s3.eu-west-3.amazonaws.com/amazon_reviews/*.parquet')
GROUP BY ALL
SETTINGS output_format_pretty_row_numbers=0
""", 'PrettyCompact')
```

让我们使用 `DESCRIBE` 子句来看一下这些 Parquet 文件的 schema：

```python theme={null}
chdb.query("""
DESCRIBE s3('s3://datasets-documentation/amazon_reviews/*.parquet')
SETTINGS describe_compact_output=1
""", 'PrettyCompact')
```

```text theme={null}
    ┌─name──────────────┬─type─────────────┐
 1. │ review_date       │ Nullable(UInt16) │
 2. │ marketplace       │ Nullable(String) │
 3. │ customer_id       │ Nullable(UInt64) │
 4. │ review_id         │ Nullable(String) │
 5. │ product_id        │ Nullable(String) │
 6. │ product_parent    │ Nullable(UInt64) │
 7. │ product_title     │ Nullable(String) │
 8. │ product_category  │ Nullable(String) │
 9. │ star_rating       │ Nullable(UInt8)  │
10. │ helpful_votes     │ Nullable(UInt32) │
11. │ total_votes       │ Nullable(UInt32) │
12. │ vine              │ Nullable(Bool)   │
13. │ verified_purchase │ Nullable(Bool)   │
14. │ review_headline   │ Nullable(String) │
15. │ review_body       │ Nullable(String) │
    └───────────────────┴──────────────────┘
```

现在我们来根据评论数量统计最热门的产品类别，并计算平均星级评分：

```python theme={null}
chdb.query("""
SELECT product_category, count() AS reviews, round(avg(star_rating), 2) as avg
FROM s3('s3://datasets-documentation/amazon_reviews/*.parquet')
GROUP BY ALL
LIMIT 10
""", 'PrettyCompact')
```

```text theme={null}
    ┌─product_category─┬──reviews─┬──avg─┐
 1. │ Toys             │  4864056 │ 4.21 │
 2. │ Apparel          │  5906085 │ 4.11 │
 3. │ Luggage          │   348644 │ 4.22 │
 4. │ Kitchen          │  4880297 │ 4.21 │
 5. │ Books            │ 19530930 │ 4.34 │
 6. │ Outdoors         │  2302327 │ 4.24 │
 7. │ Video            │   380596 │ 4.19 │
 8. │ Grocery          │  2402365 │ 4.31 │
 9. │ Shoes            │  4366757 │ 4.24 │
10. │ Jewelry          │  1767667 │ 4.14 │
    └──────────────────┴──────────┴──────┘
```

<div id="querying-files-in-a-private-s3-bucket">
  ## 查询私有 S3 存储桶中的文件
</div>

如果要查询私有 S3 存储桶中的文件，则需要传入访问密钥和密钥。
我们可以将这些凭证传递给 `s3` 表函数：

```python theme={null}
chdb.query("""
SELECT product_category, count() AS reviews, round(avg(star_rating), 2) as avg
FROM s3('s3://datasets-documentation/amazon_reviews/*.parquet', 'access-key', 'secret')
GROUP BY ALL
LIMIT 10
""", 'PrettyCompact')
```

<Note>
  此查询无法执行，因为这是一个公共 bucket！
</Note>

另一种方法是使用[命名集合](/docs/zh/concepts/features/configuration/server-config/named-collections)，但 chDB 目前尚不支持这种方式。
