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

# 필터 개요

> Pubrio 검색 필터의 작동 방식 — 통합 필터 엔진, AND/OR 의미론, 그리고 언제 어느 것을 쓸지.

Pubrio 의 검색 엔드포인트(`/companies/search`、`/people/search`、`/companies/advertisements/search`)는 단일 필터 엔진을 공유합니다. 요청 본문을 한 번 작성하면 동일한 규칙이 모든 엔드포인트에 적용됩니다 — 다중 값 필터의 결합 방식, 위치 매칭 방식, 그리고 `filter_conditions` 로 기본 연산자를 재정의하는 방식까지 포함해서.

## 왜 통합 필터 엔진인가?

<CardGroup cols={2}>
  <Card title="하나의 스키마, 세 개의 엔드포인트" icon="arrows-rotate">
    `technologies`、`verticals`、`founded_dates` 같은 회사 수준 필터는 `/companies/search`、`/people/search`、그리고 Monitor `company_filters` 에서 동일하게 동작합니다 — 한 번만 익히면 됩니다.
  </Card>

  <Card title="필터별 AND/OR" icon="code-merge">
    기본값은 OR(아무거나 일치). `filter_conditions` 에 한 줄 추가하면 개별 필터를 AND(전부 일치)로 승격할 수 있습니다 — 다른 곳은 손대지 않고요.
  </Card>

  <Card title="Postgres 네이티브 연산자" icon="database">
    배열 필터는 네이티브 Postgres 연산자로 컴파일됩니다 — OR 은 `&&`(중첩)、AND 는 `@>`(포함). 인덱스 친화적이며, 애플리케이션 단계의 후처리 필터링이 필요 없습니다.
  </Card>

  <Card title="Monitor 에서도 같은 필터" icon="bell">
    [Monitor](/ko/developer-guides/introduction) 의 `company_filters` 블록도 같은 형태를 받기 때문에, 동작하는 검색 페이로드는 그대로 동작하는 monitor 페이로드가 됩니다.
  </Card>
</CardGroup>

***

## 검색 요청의 구성

모든 검색 요청은 같은 JSON 본문 안의 세 레이어로 구성됩니다:

| 레이어     | 위치                                                           | 예시                                                                         |
| ------- | ------------------------------------------------------------ | -------------------------------------------------------------------------- |
| 인물 필터   | 최상위 키                                                        | `people_titles`、`management_levels`、`departments`、`people_locations`       |
| 회사 필터   | `company_filters: {...}` 안에 중첩(권장) — 최상위에도 허용                | `technologies`、`verticals`、`founded_dates`、`employees`、`company_locations` |
| 연산자 재정의 | `filter_conditions` 배열(회사 키를 재정의할 때는 `company_filters` 안에 둠) | `[{ "key": "technologies", "operator": "and" }]`                           |

세 레이어를 모두 사용하는 최소한의 `/people/search` 요청:

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.pubrio.com/people/search \
    -H "Content-Type: application/json" \
    -H "pubrio-api-key: YOUR_API_KEY" \
    -d '{
      "people_titles": ["VP of Engineering", "CTO"],
      "company_filters": {
        "technologies": ["Kubernetes", "Docker"],
        "is_enable_similarity_search": true,
        "company_locations": ["US"]
      },
      "per_page": 25,
      "page": 1
    }'
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      "https://api.pubrio.com/people/search",
      headers={
          "Content-Type": "application/json",
          "pubrio-api-key": "YOUR_API_KEY",
      },
      json={
          "people_titles": ["VP of Engineering", "CTO"],
          "company_filters": {
              "technologies": ["Kubernetes", "Docker"],
              "is_enable_similarity_search": True,
              "company_locations": ["US"],
          },
          "per_page": 25,
          "page": 1,
      },
  )
  print(response.json())
  ```

  ```javascript Node.js theme={null}
  const response = await fetch("https://api.pubrio.com/people/search", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "pubrio-api-key": "YOUR_API_KEY",
    },
    body: JSON.stringify({
      people_titles: ["VP of Engineering", "CTO"],
      company_filters: {
        technologies: ["Kubernetes", "Docker"],
        is_enable_similarity_search: true,
        company_locations: ["US"],
      },
      per_page: 25,
      page: 1,
    }),
  });
  console.log(await response.json());
  ```
</CodeGroup>

## `company_filters`: 회사 수준 키를 그룹으로 묶기

`company_filters: {...}` 래퍼 객체는 회사 수준 필터를 보내는 권장 방식입니다 — 어떤 키가 *인물* 을 필터하고 어떤 키가 *회사* 를 필터하는지 시각적으로 분리되며, [Monitor](/ko/developer-guides/introduction) 가 이미 사용하는 형식과 일치하므로 검색과 monitor 설정 사이에서 페이로드를 그대로 옮길 수 있습니다.

두 스타일 모두 지원됩니다. 엔진은 처리 전에 래핑 형식을 최상위로 평탄화하며, **동일 키가 있으면 최상위 키가 우선합니다**:

<CodeGroup>
  ```json 래핑형(권장) theme={null}
  {
    "people_titles": ["VP of Engineering"],
    "company_filters": {
      "technologies": [37, 152],
      "founded_dates": [2015, 2023],
      "company_locations": ["US"]
    }
  }
  ```

  ```json 평탄형(동작도 가능) theme={null}
  {
    "people_titles": ["VP of Engineering"],
    "technologies": [37, 152],
    "founded_dates": [2015, 2023],
    "company_locations": ["US"]
  }
  ```
</CodeGroup>

회사 수준 키에 대해 `filter_conditions` 재정의를 추가할 때는, 재정의되는 키와 함께 움직이도록 `company_filters` **안에** 두세요.

### `/search/similar` 변형은 동일한 본문 형태

`POST /companies/search/similar` 와 `POST /people/search/similar` 는 비유사 버전과 **동일한 필터 본문**(`company_filters` 래퍼와 `filter_conditions` 포함)을 받습니다. 각 엔드포인트는 그 위에 유사도 단계를 더 얹습니다:

|                             | 추가로 필요한 것                                                                                   | 추가로 얻는 것                                       |
| --------------------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------- |
| `/companies/search/similar` | 참조 회사 — `domain_search_id`、`domain`、`linkedin_url` 또는 `domains`                             | 각 결과에 `similarity_score`(0-1 부동소수)、유사도 내림차순 정렬 |
| `/people/search/similar`    | 참조 인물/직책 — `people_titles`、`people_search_id`、`linkedin_url`、`linkedin_urls`、`peoples` 중 하나 | 동일 — 각 결과에 `similarity_score`、유사도 내림차순         |

응답 외형은 표준 `search` 엔드포인트와 동일합니다. 필터는 유사도 랭킹 *이전* 에 후보 풀을 좁힙니다 — 따라서 `company_locations: ["US"]` 와 `/people/search/similar` 를 결합하면 그 제약 안에서 참조 직책에 가장 가까운 미국 인물이 반환됩니다. "이 조건 아래서 X 와 비슷한 사람을 더 찾기" 패턴입니다.

<Note>
  표준 `/search` 엔드포인트와 달리, `/search/similar` 는 정확한 `pagination.total_entries` 를 **반환하지 않습니다** — 유사도 검색은 관련성으로 순위를 매기고 상위 매치만 노출하므로 값은 상한에서 잘립니다. 유사도 검색은 *최고의* 매치를 찾는 용도로 사용하고, 전체를 열거하려고 하지 마세요.
</Note>

***

## AND vs OR — 필터당 한 번만 결정하면 됩니다

다중 값 필터(`technologies`、`verticals`、`keywords`、`categories` …)는 배열을 받습니다. 연산자가 "일치"의 의미를 정합니다:

<Tabs>
  <Tab title="OR (기본값)">
    **아무 값에나 일치.** 배열이 입력과 겹치는 행을 반환합니다.

    ```json theme={null}
    {
      "technologies": ["Python", "PostgreSQL", "Kubernetes"],
      "is_enable_similarity_search": true
    }
    ```

    회사의 기술 스택이 `Python`、`PostgreSQL`、`Kubernetes` 중 **하나라도** 포함하면 결과에 들어갑니다. Postgres `column && ARRAY[...]` 로 컴파일됩니다.

    사용 시점: 넓은 범위가 필요할 때 — "이 중 *어느 하나에라도* 관심", "이 중 *어느 한* 국가에 위치".
  </Tab>

  <Tab title="AND">
    **모든 값에 일치.** 배열이 모든 입력 값을 포함하는 행을 반환합니다.

    ```json theme={null}
    {
      "technologies": [37, 152, 408],
      "filter_conditions": [
        { "key": "technologies", "operator": "and" }
      ]
    }
    ```

    Numeric tag IDs come from `GET /technologies?search_term=python` (and similar). **Don't combine `is_enable_similarity_search: true` with AND on the same key** — similarity expands each free-text term into many tag IDs and `@>` then requires the row to contain all of them, which almost always returns zero.

    회사의 기술 스택이 `[37, 152, 408]` 을 **모두** 포함해야 결과에 들어갑니다. Postgres `column @> ARRAY[...]` 로 컴파일됩니다.

    사용 시점: 정밀도가 필요할 때 — "이 기술들을 *전부* 사용", "*모든* 버티컬 태그 보유".
  </Tab>
</Tabs>

<Note>
  `filter_conditions` 에 나열되지 않은 필터는 기본 연산자(배열 내부는 OR、서로 다른 필터 키 사이는 AND)를 사용합니다. 재정의만 선언하면 되고, 기본값을 적을 필요는 없습니다.
</Note>

***

## 재정의 가능한 키

엔드포인트마다 받는 키 집합이 다릅니다. 키는 각 `*_filter_conditions` 스키마의 OpenAPI enum 에서 옵니다:

<CardGroup cols={3}>
  <Card title="회사 엔드포인트" icon="building" href="/ko/api-reference/endpoint/companies/search">
    `company_filter_conditions` 키: `keywords`、`verticals`、`vertical_categories`、`vertical_sub_categories`、`technologies`、`categories`、`advertisement_target_locations`、`advertisement_exclude_target_locations`、`advertisement_search_terms`、`places`、`exclude_places`、`job_exclude_locations`.
  </Card>

  <Card title="인물 엔드포인트" icon="user" href="/ko/api-reference/endpoint/people/search">
    `people_filter_conditions` 키(회사 엔진에 위임): `keywords`、`verticals`、`vertical_categories`、`vertical_sub_categories`、`technologies`、`categories`、`places`、`exclude_places`、그리고 `social_media`.
  </Card>

  <Card title="광고 엔드포인트" icon="bullhorn" href="/ko/api-reference/endpoint/companies/advertisements_search">
    `ads_filter_conditions` 키: `target_locations`、`exclude_target_locations`. 광고는 노출 국가로만 필터링되므로 키 집합이 작습니다.
  </Card>
</CardGroup>

<Tip>
  `/people/search` 사용 시, 회사 수준 위치에 대한 `filter_conditions[].key` 는 회사 엔진의 **bare 이름** — `places`、`exclude_places` — 을 사용하며, 접두사 붙은 인물 API 이름(`company_places`)이 아닙니다. 자세한 내용은 [인물 + 회사 필터](/ko/developer-guides/filters/people-with-company-filters#key-remap-reference) 를 참조하세요.
</Tip>

***

## 성능 팁

<AccordionGroup>
  <Accordion title="인덱스된 컬럼에서 일찍 필터링" icon="bolt">
    위치, 직원 구간, `founded_dates` 는 인덱스되어 있어 자유 텍스트나 버티컬보다 후보 집합을 더 빨리 줄입니다. 1〜2 개의 정밀 필터와 결합한 뒤 유사도 검색을 시도하세요.
  </Accordion>

  <Accordion title="큰 배열에서 AND 를 남용하지 마세요" icon="triangle-exclamation">
    `column @> ARRAY[a, b, c, …]` 는 모든 값이 존재해야 합니다. 카디널리티가 빠르게 증가하며 — 평균 3 개 태그인 카테고리에서 10 개 tech 에 AND 를 걸면 거의 0 행이 반환되고 풀 스캔을 유발합니다. AND 필터는 2-4 값으로 유지하고, 탐색 쿼리는 OR 로.
  </Accordion>

  <Accordion title="자유 텍스트 입력에는 is_enable_similarity_search" icon="wand-magic-sparkles">
    slug ID(verticals、technologies、categories)를 줄 수 없고 자유 텍스트 문자열만 있다면 `is_enable_similarity_search: true`、`similarity_score: 0.7` 을 설정하세요. 엔진이 매치를 해석한 후 필터를 적용합니다 — 텍스트 스캔보다 훨씬 저렴합니다.
  </Accordion>

  <Accordion title="규모와 매출은 enum 리스트 대신 범위를 우선" icon="arrows-left-right">
    `employees: [[201, 500], [501, 1000]]`(구간 배열)와 `revenues: [1000000, 5000000]`(단일 최소/최대 범위)가 긴 ID 리스트보다 빠르고 더 자연스럽습니다.
  </Accordion>
</AccordionGroup>

***

## 다음 단계

<CardGroup cols={2}>
  <Card title="filter_conditions" icon="code-merge" href="/ko/developer-guides/filters/filter-conditions">
    레퍼런스 페이지 — 모든 지원 키, 모든 기본값, 복사 가능한 AND/OR 레시피.
  </Card>

  <Card title="인물 + 회사 필터" icon="users-rectangle" href="/ko/developer-guides/filters/people-with-company-filters">
    `/people/search` 안에서 모든 회사 필터를 사용하세요. 통합 엔진의 대표 신기능입니다.
  </Card>

  <Card title="회사 검색 레퍼런스" icon="building" href="/ko/api-reference/endpoint/companies/search">
    `/companies/search` 의 전체 요청/응답 스키마.
  </Card>

  <Card title="인물 검색 레퍼런스" icon="user" href="/ko/api-reference/endpoint/people/search">
    `/people/search` 의 전체 요청/응답 스키마.
  </Card>
</CardGroup>

<Note>
  대시보드 측 필터링 가이드를 찾고 계신가요? 지식베이스의 [연락처 필터링 및 내보내기](/ko/knowledge-base/concepts/search-filters) 를 확인하세요.
</Note>
