> ## 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.

# Операторы AND / OR

> Переопределите оператор AND/OR по умолчанию для любого мультизначного фильтра — полный справочник с примерами, готовыми к копированию.

`filter_conditions` — это единственный опциональный массив в теле запроса. Каждая запись переключает один мультизначный фильтр со стандартного поведения OR («совпадает хоть один») на AND («совпадают все»), либо наоборот. Фильтры, не перечисленные в массиве, сохраняют своё поведение по умолчанию.

## Схема

<CodeGroup>
  ```json JSON theme={null}
  {
    "filter_conditions": [
      { "key": "technologies", "operator": "and" },
      { "key": "verticals",    "operator": "or"  }
    ]
  }
  ```

  ```typescript TypeScript theme={null}
  type FilterCondition = {
    /** Имя фильтра для переопределения. См. «Поддерживаемые ключи» ниже. */
    key: string;
    /** Без учёта регистра: "and" | "or". По умолчанию для массивов — "or". */
    operator: "and" | "or";
  };

  type SearchRequest = {
    // …все остальные ваши фильтры…
    filter_conditions?: FilterCondition[];
  };
  ```
</CodeGroup>

<Note>
  `key` и `operator` обязательны в каждой записи. Запись только с `operator` молча игнорируется — глобального переопределения не существует.
</Note>

***

## Почему это важно

Оператором по умолчанию является OR, потому что большинство сценариев поиска потенциальных клиентов нацелены на широкий охват: «люди в *любой* из этих стран», «компании, отмеченные *любым* из этих тегов вертикали». Для высокоточного таргетинга — «использует *все* из `Salesforce` + `HubSpot` + `Marketo`» — нужен AND.

Цена ошибки:

* **Хотели AND, получили OR:** ответ переполнен — вы видите компании, соответствующие только одному тегу, а не всему стеку. Легко заметить, страдает качество результатов.
* **Хотели OR, получили AND:** ответ недополучает результаты — обычно возвращает почти ноль строк на мультизначных фильтрах AND, потому что реальные массивы редко содержат каждое запрошенное значение. Легко заметить, выглядит как сломанный запрос.

Под капотом движок компилирует выбранный вами оператор в нативный оператор массива Postgres: `&&` (пересечение) для OR, `@>` (содержит) для AND. Оба индексируемы, поэтому разница в стоимости — в *размере результата*, а не в задержке запроса.

***

## Поддерживаемые ключи

Точный набор ключей зависит от вызываемого эндпоинта:

| Ключ                                     | `/companies/search` | `/people/search` | `/companies/advertisements/search` | По умолчанию | Что означает `and`                                    |
| ---------------------------------------- | ------------------- | ---------------- | ---------------------------------- | ------------ | ----------------------------------------------------- |
| `technologies`                           | да                  | да               | —                                  | OR           | Имеет каждую технологию из списка                     |
| `categories`                             | да                  | да               | —                                  | OR           | Отмечена каждой категорией                            |
| `verticals`                              | да                  | да               | —                                  | OR           | Принадлежит каждой вертикали                          |
| `vertical_categories`                    | да                  | да               | —                                  | OR           | В каждой категории вертикали                          |
| `vertical_sub_categories`                | да                  | да               | —                                  | OR           | В каждой подкатегории вертикали                       |
| `keywords`                               | да                  | да               | —                                  | OR           | Описание содержит каждое ключевое слово               |
| `places`                                 | да                  | да               | —                                  | OR           | Указана в каждом месте                                |
| `exclude_places`                         | да                  | да               | —                                  | OR           | Исключена из каждого места                            |
| `advertisement_target_locations`         | да                  | —                | —                                  | OR           | Реклама таргетирует каждую страну (эндпоинт компаний) |
| `advertisement_exclude_target_locations` | да                  | —                | —                                  | OR           | Реклама исключает каждую страну                       |
| `advertisement_search_terms`             | да                  | —                | —                                  | OR           | Текст рекламы содержит каждый термин                  |
| `job_exclude_locations`                  | да                  | —                | —                                  | OR           | Вакансия исключает каждую локацию                     |
| `social_media`                           | —                   | да               | —                                  | OR           | У человека есть все перечисленные аккаунты в соцсетях |
| `target_locations`                       | —                   | —                | да                                 | OR           | Реклама таргетирует каждую страну (эндпоинт рекламы)  |
| `exclude_target_locations`               | —                   | —                | да                                 | OR           | Реклама исключает каждую страну                       |

<Tip>
  Ключи выше отражают массивы `enum` в спецификации OpenAPI (`company_filter_conditions`, `people_filter_conditions`, `ads_filter_conditions`). Отправка неподдерживаемого ключа для эндпоинта молча игнорируется.
</Tip>

***

## Рецепты

<Tabs>
  <Tab title="Все технологии (компании)">
    **Цель:** компании, использующие *все* из Python, PostgreSQL и Kubernetes — не только одну.

    <CodeGroup>
      ```bash cURL theme={null}
      curl -X POST https://api.pubrio.com/companies/search \
        -H "Content-Type: application/json" \
        -H "pubrio-api-key: YOUR_API_KEY" \
        -d '{
          "technologies": [37, 152, 408],
          "filter_conditions": [
            { "key": "technologies", "operator": "and" }
          ],
          "per_page": 25,
          "page": 1
        }'
      ```

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

      response = requests.post(
          "https://api.pubrio.com/companies/search",
          headers={
              "Content-Type": "application/json",
              "pubrio-api-key": "YOUR_API_KEY",
          },
          json={
              "technologies": [37, 152, 408],
              "filter_conditions": [
                  { "key": "technologies", "operator": "and" }
              ],
              "per_page": 25,
              "page": 1,
          },
      )
      print(response.json())
      ```

      ```javascript Node.js theme={null}
      const response = await fetch("https://api.pubrio.com/companies/search", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          "pubrio-api-key": "YOUR_API_KEY",
        },
        body: JSON.stringify({
          technologies: [37, 152, 408],
          filter_conditions: [
            { key: "technologies", operator: "and" }
          ],
          per_page: 25,
          page: 1,
        }),
      });
      console.log(await response.json());
      ```
    </CodeGroup>

    Уберите запись `filter_conditions`, чтобы расширить поиск до *любой* из трёх.
  </Tab>

  <Tab title="Любая из локаций + исключение">
    **Цель:** компании *в любой из* США, Канады или Великобритании, но никогда в Сан-Франциско.

    OR уже является значением по умолчанию для `locations`, поэтому мы оставляем его неявно. `exclude_places` обрабатывает отрицательный фильтр независимо — переопределение не требуется.

    <CodeGroup>
      ```bash cURL theme={null}
      curl -X POST https://api.pubrio.com/companies/search \
        -H "Content-Type: application/json" \
        -H "pubrio-api-key: YOUR_API_KEY" \
        -d '{
          "locations": ["US", "CA", "GB"],
          "exclude_places": ["San Francisco"],
          "per_page": 25,
          "page": 1
        }'
      ```

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

      response = requests.post(
          "https://api.pubrio.com/companies/search",
          headers={
              "Content-Type": "application/json",
              "pubrio-api-key": "YOUR_API_KEY",
          },
          json={
              "locations": ["US", "CA", "GB"],
              "exclude_places": ["San Francisco"],
              "per_page": 25,
              "page": 1,
          },
      )
      print(response.json())
      ```

      ```javascript Node.js theme={null}
      const response = await fetch("https://api.pubrio.com/companies/search", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          "pubrio-api-key": "YOUR_API_KEY",
        },
        body: JSON.stringify({
          locations: ["US", "CA", "GB"],
          exclude_places: ["San Francisco"],
          per_page: 25,
          page: 1,
        }),
      });
      console.log(await response.json());
      ```
    </CodeGroup>
  </Tab>

  <Tab title="Мультирегиональные рекламные кампании">
    **Цель:** реклама, активно таргетирующая *одновременно* ЕС и США (мультирегиональные кампании) — а не рекламу для одного рынка. Используется выделенная схема `ads_filter_conditions` с ключом `target_locations`.

    <CodeGroup>
      ```bash cURL theme={null}
      curl -X POST https://api.pubrio.com/companies/advertisements/search \
        -H "Content-Type: application/json" \
        -H "pubrio-api-key: YOUR_API_KEY" \
        -d '{
          "target_locations": ["US", "DE", "FR"],
          "filter_conditions": [
            { "key": "target_locations", "operator": "and" }
          ],
          "start_dates": ["2026-01-01"],
          "end_dates":   ["2026-04-22"],
          "per_page": 25,
          "page": 1
        }'
      ```

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

      response = requests.post(
          "https://api.pubrio.com/companies/advertisements/search",
          headers={
              "Content-Type": "application/json",
              "pubrio-api-key": "YOUR_API_KEY",
          },
          json={
              "target_locations": ["US", "DE", "FR"],
              "filter_conditions": [
                  { "key": "target_locations", "operator": "and" }
              ],
              "start_dates": ["2026-01-01"],
              "end_dates":   ["2026-04-22"],
              "per_page": 25,
              "page": 1,
          },
      )
      print(response.json())
      ```

      ```javascript Node.js theme={null}
      const response = await fetch("https://api.pubrio.com/companies/advertisements/search", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          "pubrio-api-key": "YOUR_API_KEY",
        },
        body: JSON.stringify({
          target_locations: ["US", "DE", "FR"],
          filter_conditions: [
            { key: "target_locations", operator: "and" }
          ],
          start_dates: ["2026-01-01"],
          end_dates:   ["2026-04-22"],
          per_page: 25,
          page: 1,
        }),
      });
      console.log(await response.json());
      ```
    </CodeGroup>

    <Note>
      Эндпоинт рекламы использует собственную схему `ads_filter_conditions` (меньший набор ключей: `target_locations`, `exclude_target_locations`). Ключи, которые можно переопределить на `/companies/search` и `/people/search`, здесь *не* применяются.
    </Note>
  </Tab>

  <Tab title="Люди в компаниях с несколькими технологиями">
    **Цель:** люди, работающие в компаниях, у которых установлены *одновременно* Salesforce и HubSpot — классический сигнал вытеснения CRM. Демонстрирует единый движок: тот же ключ `technologies`, тот же оператор, но на `/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": ["RevOps", "Sales Operations"],
          "technologies": [114, 287],
          "filter_conditions": [
            { "key": "technologies", "operator": "and" }
          ],
          "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": ["RevOps", "Sales Operations"],
              "technologies": [114, 287],
              "filter_conditions": [
                  { "key": "technologies", "operator": "and" }
              ],
              "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: ["RevOps", "Sales Operations"],
          technologies: [114, 287],
          filter_conditions: [
            { key: "technologies", operator: "and" }
          ],
          per_page: 25,
          page: 1,
        }),
      });
      console.log(await response.json());
      ```
    </CodeGroup>
  </Tab>
</Tabs>

***

## Распространённые ошибки

<AccordionGroup>
  <Accordion title="Забыть key, отправив только operator" icon="circle-xmark">
    Глобального переключателя «оператор по умолчанию» не существует. Каждая запись должна называть конкретный фильтр:

    ```json theme={null}
    // Игнорируется — нет key
    { "filter_conditions": [{ "operator": "and" }] }

    // Верно — переопределяет только фильтр technologies
    { "filter_conditions": [{ "key": "technologies", "operator": "and" }] }
    ```
  </Accordion>

  <Accordion title="Ожидание, что записи будут комбинироваться" icon="circle-xmark">
    Записи — это независимые переопределения для каждого ключа, они не связываются в цепочку. Указание одновременно `technologies` и `verticals` не создаёт булево выражение между ними; каждая просто задаёт оператор своего собственного массива.

    Комбинация *между* ключами фильтров всегда AND (каждый фильтр должен совпасть). Вы не можете объединить через OR два разных измерения фильтрации с помощью `filter_conditions`. Если вам нужен настоящий поиск OR-разных-фильтров, выполните два запроса и объедините результаты на стороне клиента.
  </Accordion>

  <Accordion title="Использование AND на длинном массиве" icon="triangle-exclamation">
    AND — это `column @> ARRAY[…]` — должно присутствовать каждое значение. При 8+ значениях вы почти всегда получаете ноль строк, потому что реальная разметка тегами разрежена. Держите массивы с переопределением AND в пределах 2-4 значений; используйте OR для исследовательской фильтрации или фильтрации на уровне категорий.
  </Accordion>

  <Accordion title="Неверный key в фильтрах компании на /people/search" icon="circle-xmark">
    На `/people/search` имя в people-API — `company_places` / `company_locations`. Но внутри `filter_conditions[].key` нужно использовать **имя движка** — `places`, `locations`. Переименование происходит внутри системы до того, как учитывается `filter_conditions`.

    ```json theme={null}
    // Не переопределит — движок не видит "company_places" как ключ фильтра
    { "filter_conditions": [{ "key": "company_places", "operator": "and" }] }

    // Верно
    { "filter_conditions": [{ "key": "places", "operator": "and" }] }
    ```

    Полная таблица переименования на странице [People + Company Filters](/ru/developer-guides/filters/people-with-company-filters#key-remap-reference).
  </Accordion>
</AccordionGroup>

<Tip>
  Если сомневаетесь, сначала опустите `filter_conditions` и сверьте количество результатов с ожиданиями. Добавляйте переопределения только для тех фильтров, где значение по умолчанию не соответствует вашему намерению — это делает тело запроса компактнее и облегчает отладку.
</Tip>

***

## См. также

<CardGroup cols={2}>
  <Card title="Filters Overview" icon="filter" href="/ru/developer-guides/filters/overview">
    Ментальная модель — начните отсюда, если `filter_conditions` для вас в новинку.
  </Card>

  <Card title="People + Company Filters" icon="users-rectangle" href="/ru/developer-guides/filters/people-with-company-filters">
    Как встроить фильтры по компании в `/people/search`, включая переименование ключей.
  </Card>

  <Card title="Справочник Company Search" icon="building" href="/ru/api-reference/endpoint/companies/search">
    Полная схема запроса для `/companies/search` (включает `company_filter_conditions`).
  </Card>

  <Card title="Справочник People Search" icon="user" href="/ru/api-reference/endpoint/people/search">
    Полная схема запроса для `/people/search` (включает `people_filter_conditions`).
  </Card>
</CardGroup>
