# 使用 Snaps

本指南将带你以编程方式通过 Luxonis Hub GraphQL API 管理 Snaps。你将学习如何列出 Snaps、检索详细信息以及删除它们。

> **创建 Snaps**
> 要从你的应用程序
> **发送或创建**
> Snaps，必须使用 DepthAI。请参阅
> [DepthAI 中的 Snaps](https://docs.luxonis.com/software-v3/depthai/tutorials/snaps.md)
> 文档，了解如何从应用程序中发出 Snaps。
> 本指南重点介绍如何通过 GraphQL API
> **查询、筛选和管理**
> 现有的 Snaps。

## 前提条件

在开始之前，你应该熟悉 GraphQL 基础知识。如果你是 GraphQL 新手，请查看 [关于 GraphQL](https://docs.luxonis.com/cloud/api/graphql.md)。

你还需要一个 API Key 来认证你的请求。

### 步骤 1：获取 API Key

要与 Luxonis Hub API 交互，你需要一个 API Key。API Key 提供对团队资源的完全访问权限。

请参考 [API Keys 文档](https://docs.luxonis.com/cloud/api/api-keys.md)，在 Luxonis Hub Web UI 中创建一个 Key。

一旦获得 API Key，将其包含在 Authorization 头中：

```bash
Authorization: Bearer <your_api_key>
```

### 步骤 2：列出 Snaps

使用 snaps 查询来检索团队中所有 Snaps 的列表。此查询支持基于游标的分页，以便高效浏览大型数据集。

### 基本列表查询

```graphql
query {
  team {
    snaps(first: 10) {
      nodes {
        id
        name
        createdAt
        tags
        extras
        files {
          id
          name
          classification
        }
        sourceDeviceId
        sourceAppIdentifier
      }
      pageInfo {
        hasNextPage
        endCursor
      }
    }
  }
}
```

查询解析：

 * first: 10 - 限制结果为 10 个 Snaps
 * nodes - Snap 对象数组
 * pageInfo - 分页元数据（下一页的游标）

Snap 字段说明：

 * id：唯一 Snap 标识符
 * name：Snap 名称（例如 "car_detected"、"data_collection"）
 * createdAt：Snap 创建时间戳
 * tags：用于分组的标签数组（例如 "night"、"dataset_v2"）
 * extras：包含自定义键值对的 JSON 对象，用于可搜索的元数据
 * files：附加文件数组（图像、视频、点云等）
 * sourceDeviceId：创建该 Snap 的设备 ID
 * sourceAppIdentifier：创建该 Snap 的应用程序

### 分页

要获取下一页，请使用上一响应中的 endCursor：

```graphql
query($after: String) {
  team {
    snaps(first: 10, after: $after) {
      nodes {
        id
        name
        createdAt
      }
      pageInfo {
        hasNextPage
        endCursor
      }
    }
  }
}
```

变量：

```json
{
  "after": "cursor_from_previous_response"
}
```

### 筛选 Snaps

通过多种条件筛选 Snaps 以查找特定数据：

按时间范围筛选：

```graphql
query($from: DateTime!, $to: DateTime!) {
  team {
    snaps(
      first: 10,
      filter: {
        createdFrom: $from,
        createdTo: $to
      }
    ) {
      nodes {
        id
        name
        createdAt
      }
    }
  }
}
```

变量：

```json
{
  "from": "2024-01-01T00:00:00Z",
  "to": "2024-02-01T00:00:00Z"
}
```

按设备筛选：

```graphql
query {
  team {
    snaps(
      first: 10,
      filter: { deviceId: "device-id" }
    ) {
      nodes {
        id
        name
        sourceDeviceId
      }
    }
  }
}
```

按应用标识符筛选：

```graphql
query {
  team {
    snaps(
      first: 10,
      filter: { deviceAppIdentifier: "my-app" }
    ) {
      nodes {
        id
        name
        sourceAppIdentifier
      }
    }
  }
}
```

按名称筛选：

```graphql
query {
  team {
    snaps(
      first: 10,
      filter: { name: "car_detected" }
    ) {
      nodes {
        id
        name
      }
    }
  }
}
```

按标签筛选：

```graphql
query {
  team {
    snaps(
      first: 10,
      filter: { tags: ["night", "validation"] }
    ) {
      nodes {
        id
        name
        tags
      }
    }
  }
}
```

按额外字段（自定义元数据）筛选：

```graphql
query {
  team {
    snaps(
      first: 10,
      filter: { extras: { scene: "warehouse", lighting: "low" } }
    ) {
      nodes {
        id
        name
        extras
      }
    }
  }
}
```

按文件分类筛选：

```graphql
query {
  team {
    snaps(
      first: 10,
      filter: { withFilesClassifiedAs: [IMAGE_COLOR, VIDEO] }
    ) {
      nodes {
        id
        name
        files {
          classification
        }
      }
    }
  }
}
```

可用的文件分类：

 * IMAGE_COLOR：彩色图像
 * IMAGE_STEREO_LEFT：左立体图像
 * IMAGE_STEREO_RIGHT：右立体图像
 * VIDEO：视频文件
 * POINTCLOUD：点云数据
 * ANNOTATION：注释文件
 * DISPARITY：视差图
 * UNKNOWN_FILE：其他文件类型

组合多个筛选条件：

```graphql
query {
  team {
    snaps(
      first: 10,
      filter: {
        deviceId: "device-id",
        tags: ["validation"],
        createdFrom: "2024-01-01T00:00:00Z"
      }
    ) {
      nodes {
        id
        name
        tags
        createdAt
      }
    }
  }
}
```

### 步骤 3：加载单个 Snap

通过 ID 检索特定 Snap 的详细信息，包括文件下载 URL。

```graphql
query($snapId: ID!) {
  team {
    snap(snapId: $snapId) {
      id
      name
      createdAt
      tags
      extras
      files {
        id
        name
        hash
        mimeType
        size
        presignedUrl
        classification
      }
      sourceDeviceId
      sourceSerialNumber
      sourceAppIdentifier
    }
  }
}
```

变量：

```json
{
  "snapId": "snap-id-from-list"
}
```

响应示例：

```json
{
  "data": {
    "team": {
      "snap": {
        "id": "snap-abc123",
        "name": "car_detected",
        "createdAt": "2024-01-15T10:30:00Z",
        "tags": ["validation", "warehouse"],
        "extras": { "scene": "warehouse", "lighting": "low" },
        "files": [
          {
            "id": "file-xyz789",
            "name": "image.jpg",
            "hash": "abc123...",
            "mimeType": "image/jpeg",
            "size": 524288,
            "presignedUrl": "https://storage.example.com/snap-abc123/image.jpg?signature=...",
            "classification": "IMAGE_COLOR"
          }
        ],
        "sourceDeviceId": "device-123",
        "sourceSerialNumber": "OAK123456",
        "sourceAppIdentifier": "detection-app"
      }
    }
  }
}
```

关键字段说明：

 * presignedUrl：直接、有时限的文件下载 URL。使用此 URL 无需身份验证即可下载文件。
 * hash：用于完整性校验的文件校验和
 * mimeType：文件的 MIME 类型（例如 "image/jpeg"、"video/mp4"）
 * size：文件大小（字节）
 * sourceSerialNumber：创建该 Snap 的设备序列号
 * sourceAppIdentifier：发出该 Snap 的应用程序标识符

### 步骤 4：删除 Snaps

通过 ID 或应用筛选条件来删除 Snaps。删除操作作为后台任务异步执行。

> **异步删除**
> Snap 删除不是即时的。API 返回一个
> `bgTaskId`
> ，可用于跟踪删除进度。

### 方法 1：按 ID 删除

通过 ID 删除特定 Snaps：

```graphql
mutation DeleteSnapsByIds($ids: [ID!]!) {
  team {
    deleteSnapsByIds(ids: $ids) {
      status
      bgTaskId
    }
  }
}
```

变量：

```json
{
  "ids": ["snap-id-1", "snap-id-2", "snap-id-3"]
}
```

响应:

```json
{
  "data": {
    "team": {
      "deleteSnapsByIds": {
        "status": "SUCCESS",
        "bgTaskId": "bg-task-abc123"
      }
    }
  }
}
```

### 方法2：按过滤器删除

删除符合特定条件的快照：

```graphql
mutation DeleteSnapsByFilter {
  team {
    deleteSnapsByFilter(
      filter: {
        deviceId: "device-id",
        createdFrom: "2024-01-01T00:00:00Z",
        createdTo: "2024-02-01T00:00:00Z",
        tags: ["test"]
      }
    ) {
      status
      bgTaskId
    }
  }
}
```

可用的删除过滤器：

 * deviceId：删除指定设备的快照
 * deviceAppId：删除指定应用实例的快照
 * deviceAppIdentifier：删除具有此标识符的应用的快照
 * createdFrom：删除此时间戳之后创建的快照
 * createdTo：删除此时间戳之前创建的快照
 * name：删除此名称的快照
 * tags：删除包含这些标签的快照
 * extras：删除包含这些自定义元数据的快照
 * withFilesClassifiedAs：删除包含此分类文件的快照

### 检查删除状态

使用 bgTaskId 跟踪删除进度：

```graphql
query($bgTaskId: ID!) {
  team {
    bgTask(bgTaskId: $bgTaskId) {
      id
      state {
        deletedCount
        totalCount
      }
      createdAt
      completedAt
      failedAt
    }
  }
}
```

变量：

```json
{
  "bgTaskId": "bg-task-id-from-deletion"
}
```

响应（进行中）：

```json
{
  "data": {
    "team": {
      "bgTask": {
        "id": "bg-task-abc123",
        "state": {
          "deletedCount": 150,
          "totalCount": 500
        },
        "createdAt": "2024-01-15T11:00:00Z",
        "completedAt": null,
        "failedAt": null
      }
    }
  }
}
```

响应（已完成）：

```json
{
  "data": {
    "team": {
      "bgTask": {
        "id": "bg-task-abc123",
        "state": {
          "deletedCount": 500,
          "totalCount": 500
        },
        "createdAt": "2024-01-15T11:00:00Z",
        "completedAt": "2024-01-15T11:05:30Z",
        "failedAt": null
      }
    }
  }
}
```

### 状态值

删除响应中的 status 字段可能为：

 * SUCCESS：删除任务创建成功
 * IDS_NOT_FROM_TEAM：一个或多个快照 ID 不属于您的团队
 * BG_TASK_LIMIT_REACHED：正在运行的后台任务过多，请稍后重试

## 总结

在本指南中，您学习了如何：

 * 分页列出快照并进行过滤
 * 获取单个快照的详细信息
 * 使用预签名 URL 下载快照文件
 * 按 ID 或使用过滤器删除快照
 * 通过后台任务跟踪删除进度

> **要点总结**
> - 使用
> **标签和附加信息**
> 实现快照的有效组织和搜索
> - 善用
> **过滤器**
> 查询数据的特定子集
> - **删除是异步操作**
> - 务必通过
> `bgTaskId`
> 检查进度
> - **预签名 URL 有时间限制**
> - 请及时下载文件

## 下一步

 * 查看 [快照功能文档](https://docs.luxonis.com/cloud/features/event-storage/snaps.md) 了解如何通过 Luxonis Hub UI 管理快照
 * 学习如何使用 DepthAI [从您的应用发送快照](https://docs.luxonis.com/software-v3/depthai/tutorials/snaps.md)
 * 浏览 [完整模式参考](https://docs.luxonis.com/cloud/api/reference/control-api/schema.md) 了解所有与快照相关的类型和变更操作
 * 发现更多 [自动化指南](https://docs.luxonis.com/cloud/api/guides.md) 获取其他 API 集成示例
