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

# 필터링

> 셀렉터 단축키와 where 인자로 쿼리 결과 필터링 — 연산자, 중첩 필터, OR 로직, 기본값

ChainStream GraphQL에서 데이터를 필터링하는 방법은 두 가지입니다:

1. **Selector shortcuts** — `tokenAddress` 같은 최상위 인자로, 흔한 필터를 간편히 쓰는 약칭
2. **`where` 인자** — 연산자 전 범위와 임의 차원 필터를 지원하는 중첩 필터 객체

<Warning>
  **권장: 항상 시간 필터를 넣으세요.** DEXTrades, Transfers, BalanceUpdates 같은 DWD(상세) Cube에서 `Block.Time` 필터 없이 쿼리하면 매우 큰 테이블 파티션을 스캔할 수 있습니다. 스캔 범위를 제한하려면 항상 `where: {Block: {Time: {after: "..."}}}` 를 포함하고, OLAP 엔진의 메모리 한계를 피하세요.
</Warning>

같은 쿼리에서 둘을 함께 사용할 수 있습니다.

***

## Selector shortcuts

Selector는 Cube 필드의 **편의 인자**로, 흔한 `where` 필터 패턴에 매핑됩니다. 단순 문자열이 아니라 `where` 필드와 동일한 필터 입력 타입(예: `is`, `in`, `like` 가 있는 `StringFilter`)을 받습니다.

| Selector          | 매핑 대상                 | 사용 가능 Cube                                                                                                     |
| :---------------- | :-------------------- | :------------------------------------------------------------------------------------------------------------- |
| `tokenAddress`    | 각 Cube의 주요 토큰 주소 컬럼   | DEXTrades, Transfers, BalanceUpdates, DEXPools, TokenSupplyUpdates, Pairs, Tokens, DEXPoolEvents, TokenHolders |
| `walletAddress`   | 지갑/계정 소유자 주소          | DEXTrades, WalletTokenPnL                                                                                      |
| `poolAddress`     | 풀 컨트랙트 주소             | DEXTrades, DEXPools                                                                                            |
| `senderAddress`   | 전송 송신 주소              | Transfers                                                                                                      |
| `receiverAddress` | 전송 수신 주소              | Transfers                                                                                                      |
| `ownerAddress`    | 토큰 계정 소유자 주소          | BalanceUpdates                                                                                                 |
| `dexProgram`      | DEX 프로그램/컨트랙트 주소      | DEXTrades                                                                                                      |
| `date`            | 블록 타임스탬프(DateTime 필터) | DEXTrades, Transfers, BalanceUpdates, DEXPools                                                                 |

**아래 두 쿼리는 동일합니다:**

<Tabs>
  <Tab title="Selector 사용">
    ```graphql theme={null}
    query {
      Solana {
        DEXTrades(
          tokenAddress: {is: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"}
          limit: { count: 10 }
        ) {
          Block { Time }
          Trade { Buy { Amount PriceInUSD } }
        }
      }
    }
    ```
  </Tab>

  <Tab title="where 필터 사용">
    ```graphql theme={null}
    query {
      Solana {
        DEXTrades(
          where: {
            Trade: {
              Buy: {
                Currency: {
                  MintAddress: {
                    is: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
                  }
                }
              }
            }
          }
          limit: { count: 10 }
        ) {
          Block { Time }
          Trade { Buy { Amount PriceInUSD } }
        }
      }
    }
    ```
  </Tab>
</Tabs>

<Tip>
  Selector는 정확 일치만이 아니라 모든 필터 연산자를 지원합니다. 예: `tokenAddress: {in: ["ADDR_1", "ADDR_2"]}` 로 여러 토큰을 매칭하고, `date: {after: "2025-01-01T00:00:00Z"}` 로 시간을 필터할 수 있습니다.
</Tip>

***

## `where` 인자

`where` 인자는 Cube의 차원 계층을 반영한 중첩 입력 객체를 받습니다. 각 리프 필드는 타입이 지정된 연산자를 가진 **필터 프리미티브**에 매핑됩니다.

### 구조

```graphql theme={null}
where: {
  DimensionGroup: {
    DimensionField: {
      operator: value
    }
  }
}
```

**예** — 블록 시간이 특정 날짜 이후이고 매수 금액이 1000보다 큰 DEXTrades만 필터:

```graphql theme={null}
query {
  Solana {
    DEXTrades(
      where: {
        Block: { Time: { after: "2025-01-01T00:00:00Z" } }
        Trade: { Buy: { Amount: { gt: 1000 } } }
      }
      limit: { count: 20 }
    ) {
      Block { Time }
      Trade { Buy { Amount PriceInUSD } }
    }
  }
}
```

`where` 의 같은 레벨에 여러 필드를 지정하면 **AND** 로 결합됩니다.

***

## 필터 프리미티브 타입

모든 리프 차원은 다음 필터 입력 타입 중 하나에 매핑됩니다:

### StringFilter

주소, 해시, 프로토콜 이름 등 텍스트 필드용.

| 연산자     | 타입          | 설명                     |
| :------ | :---------- | :--------------------- |
| `is`    | `String`    | 정확 일치                  |
| `not`   | `String`    | 같지 않음                  |
| `in`    | `[String!]` | 목록 중 하나와 일치            |
| `notIn` | `[String!]` | 목록의 모든 값 제외            |
| `like`  | `String`    | SQL LIKE 패턴(`%` 와일드카드) |

```graphql theme={null}
where: {
  Trade: {
    Dex: {
      ProtocolName: { in: ["Raydium", "Orca"] }
    }
  }
}
```

### IntFilter / FloatFilter

금액, 가격, 건수 등 숫자 필드용.

| 연산자     | 타입          | 설명          |
| :------ | :---------- | :---------- |
| `eq`    | `Number`    | 같음          |
| `ne`    | `Number`    | 같지 않음       |
| `gt`    | `Number`    | 보다 큼        |
| `gte`   | `Number`    | 이상          |
| `lt`    | `Number`    | 보다 작음       |
| `lte`   | `Number`    | 이하          |
| `in`    | `[Number!]` | 목록 중 하나와 일치 |
| `notIn` | `[Number!]` | 목록의 모든 값 제외 |

```graphql theme={null}
where: {
  Trade: {
    Buy: {
      PriceInUSD: { gte: 0.001, lte: 1.0 }
    }
  }
}
```

### DateTimeFilter

타임스탬프 필드용. 값은 ISO 8601 문자열입니다.

| 연산자       | 타입                       | 설명             |
| :-------- | :----------------------- | :------------- |
| `after`   | `DateTime`               | 이 시각 이후(배타)    |
| `before`  | `DateTime`               | 이 시각 이전(배타)    |
| `since`   | `DateTime`               | 이 시각 이후(포함)    |
| `till`    | `DateTime`               | 이 시각까지(포함)     |
| `between` | `[DateTime!, DateTime!]` | 두 시각 사이(양끝 포함) |

```graphql theme={null}
where: {
  Block: {
    Time: { since: "2025-03-01T00:00:00Z", till: "2025-03-31T23:59:59Z" }
  }
}
```

<Note>
  `after`/`before`는 **배타**(엄격한 부등호)입니다. `since`/`till`은 **포함**입니다. `between`은 두 요소 배열이며 양끝 모두 포함입니다.
</Note>

### BoolFilter

불리언 필드용.

| 연산자  | 타입        | 설명                     |
| :--- | :-------- | :--------------------- |
| `eq` | `Boolean` | `true` 또는 `false` 와 같음 |

```graphql theme={null}
where: {
  IsSuspect: { eq: true }
}
```

***

## `any` 로 OR 논리

기본적으로 `where` 안의 조건은 모두 AND로 결합됩니다. OR를 쓰려면 `any` 배열 필드를 사용합니다 — 각 요소는 완전한 필터 객체이며, **하나라도** 맞는 레코드가 반환됩니다.

```graphql theme={null}
query {
  Solana {
    DEXTrades(
      where: {
        any: [
          { Trade: { Buy: { Currency: { MintAddress: { is: "TOKEN_A" } } } } }
          { Trade: { Buy: { Currency: { MintAddress: { is: "TOKEN_B" } } } } }
        ]
      }
      limit: { count: 20 }
    ) {
      Trade {
        Buy { Currency { MintAddress } Amount }
      }
    }
  }
}
```

<Info>
  `any` 는 다른 최상위 `where` 필드와 함께 쓸 수 있습니다. `any` 조건들은 OR로 묶이고, 그 결과가 형제 조건들과 AND로 결합됩니다.
</Info>

***

## 기본 필터

일부 Cube는 기본 필터를 자동 적용합니다. `where` 절에서 명시적으로 설정하면 덮어쓸 수 있습니다.

| Cube      | 기본 필터               | 효과                |
| :-------- | :------------------ | :---------------- |
| DEXTrades | `IsSuspect = false` | 기본적으로 봇/MEV 거래 제외 |

**의심(suspect) 거래를 포함**하려면 필터를 명시하세요:

```graphql theme={null}
query {
  Solana {
    DEXTrades(
      where: { IsSuspect: { eq: true } }
      limit: { count: 10 }
    ) {
      Block { Time }
      Trade { Buy { Amount } }
      IsSuspect
    }
  }
}
```

또는 `where` 에 `IsSuspect` 를 아예 넣지 않으면 기본값 `false` 가 그대로 적용됩니다. 의심 여부와 관계없이 **모든** 거래를 보려면 OR를 사용합니다:

```graphql theme={null}
where: {
  any: [
    { IsSuspect: { eq: true } }
    { IsSuspect: { eq: false } }
  ]
}
```

***

## Selector와 `where` 결합

Selector와 `where` 는 AND로 결합됩니다. 주요 엔티티는 Selector로, 추가 조건은 `where` 로 좁힐 수 있습니다:

```graphql theme={null}
query {
  Solana {
    DEXTrades(
      tokenAddress: {is: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"}
      where: {
        Block: { Time: { after: "2025-03-01T00:00:00Z" } }
        Trade: { Buy: { Amount: { gt: 100 } } }
      }
      orderBy: {descending: Block_Time}
      limit: { count: 50 }
    ) {
      Block { Time }
      Transaction { Hash }
      Trade {
        Buy { Amount PriceInUSD }
        Sell { Currency { MintAddress } Amount }
        Dex { ProtocolName }
      }
    }
  }
}
```

이 쿼리는 Solana에서 매수 금액이 100을 넘는 USDC 거래 중 최근 50건을 시간 내림차순으로 가져옵니다.

***

## 다음 단계

<CardGroup cols={2}>
  <Card title="정렬 및 페이지네이션" icon="arrow-down-1-9" href="/ko/graphql/schema/ordering-pagination">
    `orderBy` 와 `limit` 으로 결과를 정렬하고 페이지를 넘깁니다.
  </Card>

  <Card title="메트릭 및 집계" icon="chart-simple" href="/ko/graphql/schema/metrics-aggregation">
    count, sum, avg, min, max, uniq 로 필터된 데이터를 집계합니다.
  </Card>
</CardGroup>
