---
metadata:
  - name: generator
    content: Diplodoc Platform v5.50.6
alternate:
  - https://ytsaurus.tech/docs/en/user-guide/storage/ypath.md
  - https://ytsaurus.tech/docs/ru/user-guide/storage/ypath.md
---
> **Documentation Index:** Fetch the complete configuration index at https://ytsaurus.tech/docs/ru/llms.txt

<!-- source: ru/_includes/user-guide/storage/ypath.md -->
# YPATH

В данном разделе собрана информация про YPath — язык, описывающий пути к объектам в системе YTsaurus.

YPath представляет собой язык описания путей, которые идентифицируют объекты в системе YTsaurus. Язык позволяет обращаться к узлам и указывать аннотации, которые могут быть полезны при совершении операций над узлами, например, при записи в таблицу. При помощи аннотаций можно определить, будут ли новые данные дописаны в конце таблицы, или таблица будет полностью перезаписана.

Например:

- `//home/user/table` — путь к таблице `table` в домашнем каталоге пользователя;
- `#0-25-3ec012f-406daf5c/@type` — путь к атрибуту `type` объекта с идентификатором `0-25-3ec012f-406daf5c`;
- `//home/user/table[#10:#20]` — строки с 10-ю по 19-ю включительно таблицы `table` в домашнем каталоге пользователя.

Существует несколько разновидностей YPath. В самом простом случае YPath представляет собой строку, кодирующую путь.

## Простой YPath { #simple_ypath }

### Лексика { #simple_ypath_lexis }

Строка, кодирующая простой YPath, разбивается на следующие **токены**:

1. **Специальные символы**: прямой слеш (`/`), «собака» (`@`), амперсанд (`&`), звёздочка (`*`);
2. **Литералы**: максимальная непустая последовательность неспециальных символов. В литералах разрешен escaping вида `\<escape-sequence>`, где в качестве `<escape-sequence>` может выступать один из символов `\`, `/`, `@`, `&`, `*`, `[`, `{`, а также выражение вида `x<hex1><hex2>`, где `<hex1>` и `<hex2>` — шестнадцатеричные цифры.

### Синтаксис и семантика { #simple_ypath_syntax }

Структурно YPath имеет вид `<root-designator><relative-path>`. Здесь `<root-designator>` бывает двух видов:

1. **Корень Кипариса**: токен `/`.
   Пример: `//home/user`; здесь `<root-designator>` равен `/`, а `<relative-path>` равен `/home/user`;
2. **Объектный корень**: токен-литерал, кодирующий строку вида `#<id>`.
   Пример: `#1-2-3-4/@type`; здесь `<root-designator>` равен `#1-2-3-4`, а `<relative-path>` равен `/@type`.

Тем самым, `<root-designator>` определяет начальную точку отсчета, к которой применяется `<relative-path>`. Последний разбирается последовательно слева направо, в результате чего возникают шаги перемещения по дереву следующих видов:

- **Переход к потомку**: последовательность из токена `/` и литерала.
  Данный тип шагов применим к словарям и спискам. В случае словаря литерал должен содержать имя потомка. Пример: `/child` — переход к потомку с именем `child`.
  В случае списка литерал должен содержать целое число в десятичной системе счисления — номер потомка. Потомки в списке нумеруются с нуля. Разрешены также отрицательные номера, которые нумеруют потомков с конца списка. Примеры: `/1` — переход ко второму потомку в списке, `/-1` — переход к последнему потомку в списке;
- **Переход к атрибуту**: последовательность из токенов `/@` и литерала.
  Данный тип шагов применим в любой точке пути и означает переход к атрибуту с данными именем. Пример: `/@attr` — переход к атрибуту с именем `attr`.

{% note info "Примечание" %}

В YPath относительные пути начинаются со слешей. Тем самым, слеш служит не разделителем как в случае файловых систем, а полноправным членом команды перемещения по дереву метаинформации. В частности, для склейки двух YPath достаточно обычной конкатенации строк.

{% endnote %}

{% note warning "Внимание" %}

Количество *переходов к потомку,* содержащееся в пути, ограничено. Попытка обратиться по пути, превышающему этот лимит, завершится ошибкой. Лимит равен 256, но может быть изменен в будущем.

{% endnote %}

###  Примеры { #simple_ypath_examples }

```
% Корень Кипариса
/

% В корневой директории узел home, в ней — узел user.
//home/user

% Начальный элемент в списке //home/user/list
//home/user/list/0

% Последний элемент в списке //home/user/list
//home/user/list/-1

% Атрибут attr узла //home/user
//home/user/@attr

% Объект с идентификатором 1-2-a-b
#1-2-a-b

% Потомок child объекта с идентификатором 1-2-a-b
#1-2-a-b/child

% Атрибут attr объекта с идентификатором 1-2-a-b
#1-2-a-b/@attr
```

### Особенности поведения { #simple_ypath_behavior }

Помимо указанных выше правил действует ряд специальных соглашений. Большинство из них связано с тем, что YPath может идентифицировать не только уже существующие метаинформационные сущности, но и новые, создаваемые в момент выполнения команды, аргументом которой служит данный YPath.

- **Указание всех потомков**: в команде `remove_node` есть возможность удалить всех потомков словаря или списка, для этого следует использовать вместо имени токен `*`.
  Пример:

  ```
  % Очистить домашний каталог пользователя
  yt remove //home/user/*
  ```

- **Указание всех атрибутов**: в командах чтения (`get_node`, `list_nodes`) есть возможность обратиться к коллекции всех атрибутов объекта, для чего в качестве пути надо использовать путь вида `/@`.

  Примеры:

  ```
  % Получить значения всех атрибутов домашнего каталога пользователя
  yt get //home/user/@

  % Получить имена всех атрибутов домашнего каталога пользователя
  yt list //home/user/@
  ```

  Также есть возможность *изменения* коллекции всех атрибутов с помощью команды `set_node`, однако следует понимать, что атрибуты, не перечисленные в устанавливаемом значении, будут удалены.

  Примеры:

  ```
  % Удалить все атрибуты
  yt set //home/user/@ '{}'

  % Выставить два атрибута, удалив все остальные имеющиеся
  yt set //home/user/@ '{attr1=value1; attr2=value2}'
  ```

  При работе с Кипарисом (а не с абстрактным yson-документом) описанной возможностью пользоваться не следует, поскольку это может привести к непреднамеренному удалению системных атрибутов узла. Вместо этого стоит модифицировать необходимые атрибуты индивидуально.

  Примеры:

  ```
  % Выставить один пользовательский атрибут, не трогать остальные
  yt set //home/user/@attr value

  % Выставить вложенный пользовательский атрибут
  yt set //home/user/@attr/some/key value
  ```

- **Указание позиции вставки в список**: в командах, создающих новые узлы (например `set_node`) есть возможность указать положение создаваемого узла в списке относительно уже имеющихся. Для этого нужно вместо номера потомка использовать специальные строки `begin` (начало списка), `end` (конец списка), `before:<index>` (позиция перед потомком с номером `<index>`), а также `after:<index>` (позиция после потомка с номером `<index>`). Примеры:

  ```
  % Добавить элемент "value" в конец списка //home/user/list
  yt set //home/user/list/end value

  % Вставить элемент "value" в начало списка //home/user/list
  yt set //home/user/list/before:0 value
  % Или
  yt set //home/user/list/begin value

  % Вставить элемент "value" перед вторым элементом списка //home/user/list
  yt set //home/user/list/before:2 value

  % Вставить элемент "value" после пятого элемента списка //home/user/list
  yt set //home/user/list/after:5 value
  ```

- **Отключение перенаправления**: токен `&` может использоваться для подавления перенаправления по [символической ссылке](https://ytsaurus.tech/docs/ru/user-guide/storage/links.md).
  Примеры:

  ```
  % Узнать идентификатор самого объекта-ссылки, а не объекта, на который ссылка указывает
  yt get //home/user/link&/@id
  ```

## Сложный YPath { #rich_ypath }

**Сложный** (**rich**) YPath представляет собой расширенный YPath, имеющий вид строки с дополнительными аннотациями. Эти аннотации могут быть заданы двумя способами: в виде **атрибутов** (пар вида ключ-значение), а также **синтаксически** с помощью добавления специальных префиксов и суффиксов к простому YPath, из-за чего он превращается в строку вида `<prefix><simple-ypath><suffix>`.

При отсутствии префикса `<prefix>` и суффикса `<suffix>` сложный YPath может иметь, например, такой вид:

```
<
  append = %true;
  compression_codec = lz4;
>
//home/user/table
```

Данный путь указывает на домашний каталог пользователя и несет в себе два атрибута.

На любом пути можно указать произвольный набор атрибутов. Точный их смысл зависит от того, как данный путь используется в системе. Например, при записи в таблицу имеет смысл атрибут `append`, позволяющий дописывать в конец, а не перезаписать результат. Для входных таблиц некоторых mapreduce-операций можно указать флаг `foreign`, означающий, что данная таблица является вторичной (таблицей-справочником), поэтому системе необходимо выполнять join специального вида.

Атрибуты, имена которых системе неизвестны, или которые не имеют смысла в заданном контексте, системой игнорируются.

Префикс и суффикс пути позволяют закодировать атрибуты в более компактном виде. Обе эти части используют лексику [YSON](https://ytsaurus.tech/docs/ru/user-guide/storage/yson.md). Подробнее об их устройстве:

### Префикс { #rich_ypath_prefix }

Часть `<prefix>` либо пуста, либо задает атрибуты в виде map-fragment в формате [YSON](https://ytsaurus.tech/docs/ru/user-guide/storage/yson.md).
Пример: `<append=%true>//home/user/table` задает путь к таблице в домашнем каталоге пользователя, а также сообщает нам дополнительный атрибут `append`.

Вдобавок к словарю произвольных атрибутов, поддерживается также короткая запись вида `my_cluster://path/to/object`. Такая запись полностью эквивалентна указанию атрибута `cluster` в словаре атрибутов (`<cluster=my_cluster>//path/to/object`).

В случае, когда кластер указан и через атрибуты, и через короткую запись, приоритет отдается кластеру, указанному через короткую запись.

Основное предназначение префикса — упростить передачу атрибутов при использовании команд из консоли.

### Суффикс { #rich_ypath_suffix }

Часть `<suffix>` либо пуста, либо указывает колонки и/или диапазоны строк обрабатываемой таблицы.

Сначала всегда указываются модификатор выбора колонок, если он есть, а затем модификатор выбора строк, если он есть.

**Модификатор выбора колонок** представляет собой разделенный запятыми и взятый в фигурные скобки набор имен колонок. Каждое имя представлено YSON-строкой.

Примеры модификаторов выбора колонок: `{a}`, `{a,b}`, `{}` .

Формальная грамматика модификаторов выбора колонок:

```
<column-selector> = '{' { <column-selector-item> ',' } [ <column-selector-item> ] '}'
<column-selector-item> = <string>
```

**Модификатор выбора строк** представляет собой разделенный запятыми и взятый в квадратные скобки набор диапазонов строк таблицы. Каждый диапазон — пара из нижней и верхней границы диапазона, разделенных двоеточием, либо точное значение границы, которую нужно прочитать. В случае пары одна или обе границы могут отсутствовать.
Граница может быть либо числом с приписанным слева символом `#` — тогда это номер строки в таблице, либо списком значений — тогда это граница по значениям ключевых колонок, по которым таблица отсортирована. Указанный список может быть короче, чем количество полей, по котором отсортирована таблица. В случае, если список состоит из одного элемента, его можно не обрамлять в круглые скобки. Элемент должен быть корректным YSON-значением скалярного типа `int64`, `uint64`, `string`, `double`, `bool`.

Семантика модификатора выбора строк описана в [разделе](#key_selectors).

Примеры модификаторов выбора строк: `[:]`, `[#10:#100]`, `[a:m]`, `[(abc,8):(xyz,5)]`, `[:5.0,10.0:]`, `[#10]`, `[a,#100,#1:#2]`, `[100u:200u]`. В последнем случае данные содержат беззнаковые числа.

Формальная грамматика модификаторов выбора строк:

```
<row-selector> = '[' { <row-range> ',' } [ <row-range> ] ']'

<row-range> = <row-index-range-selector> | <row-key-range-selector> | <row-index> | <row-composite-key> | ''

<row-index-range-selector> = [ <row-index> ] ':' [ <row-index> ]

<row-index> = '#' <int64>

<row-key-range-selector> = [ <row-composite-key> ] ':' [ <row-composite-key> ]

<row-composite-key> = <row-key> | <row-key-tuple>

<row-key-tuple> = '(' { <row-key> ',' } [ <row-key> ] ')'

<row-key> = <string> | <int64> | <uint64> | <bool> | <double>
```

### Примеры  { #rich_ypath_examples }

{% note info "Примечание" %}

Сложные пути взяты в одинарные кавычки для надлежащего парсинга шеллом.

{% endnote %}

```
% Прочитать целиком таблицу '//home/user/table'
yt read '//home/user/table'

% Прочитать все строки таблицы '//home/user/table', но не выбрать ни одной колонки
yt read '//home/user/table{}'

% Прочитать колонку 'a'
yt read '//home/user/table{a}'

% Прочитать колонки 'a', 'b'
yt read '//home/user/table{a,b}'

% Прочитать первые 100 строк таблицы '//home/user/table' (и выбрать все колонки)
yt read '//home/user/table[#0:#100]'

% Прочитать все строки, пропустив первые 100
yt read '//home/user/table[#100:]'

% Прочитать строку с номером 100 (считая с 0)
yt read '//home/user/table[#100]'

% Прочитать строки с ключом (или первой координатой ключа) 'abc'
yt read '//home/user/table["abc":"abc\x00"]'

% Запрос выше можно также выразить короче:
yt read '//home/user/table["abc"]'

% Прочитать строки с ключами, не меньшими '(a,1)'
yt read '//home/user/table[(a,1):]'

% Прочитать строки у которых первые две компоненты ключа равны 'a' и '1' соответственно
yt read '//home/user/table[(a,1)]'

% Прочитать строки, у которых первый ключ 'a', второй ключ начинается с 'b', и, если второй ключ равен 'b', то третий ключ не меньше '1'.
yt read '//home/user/table[(a,b,1):(a,c)]'

% Прочитать строки, у которых первый ключ начинается с 'a', а также строки, у которых первый ключ 'b', а второй - меньше '1'.
yt read '//home/user/table[a:(b,1)]'

% Прочитать строки, у которых первый ключ начинается с 'a', а также строки, у которых первый ключ 'b', а второй - меньше '1', а также строки, у которых первый ключ 'b', второй ключ - '1', а третий - отрицательный типа double. Выбрать колонки 'ab', 'ac'
yt read '//home/user/table{ab,ac}[a:(b,1,0.0)]'

% Преобразовать table1 со столбцами a,b,c,d в table2 со столбцами a,b,c и сортировкой по полям a,b
yt sort --src '//home/users/table1{a,b,c}' --dst //home/users/table2 --sort-by a --sort-by b --spec '{schema_inference_mode = from_output}'

% Преобразовать table1 со столбцами a,b,c,d в table2 со столбцами a,b,c
yt merge --src '//home/users/table1{a,b,c}' --dst //home/users/table2 --spec '{schema_inference_mode = from_output}'
```

## Каноническая форма YPath { #ypath_canonical_form }

[Сложный YPath](#rich_ypath) может быть приведен к **канонической форме**, в которой отсутствуют префикс и суффикс, вся информация из которых явно вынесена в атрибуты, назначенные строке — [простому YPath](#simple_ypath).

Пример: после канонизации пути `<append=true>//home/user/table[#10:#20]` получается следующая YSON-структура:

```
<
  append = true;
  ranges = [
    {
      lower_limit = {row_index = 10};
      upper_limit = {row_index = 20}
    }
  ]
>
"//home/user/table"
```

Внутри система YTsaurus предпочитает работать с канонической формой путей. Эта форма более громоздка, поэтому во всех путях, принимаемых системой на вход, разрешается использовать более удобную форму с префиксом и суффиксом:

```
<append=true>//home/user/table[#10:#20]
```
Префикс — `<append=true>`;

Суффикс — `[#10:#20]`.

Внутри системы это будет развернуто в широкую запись:

```
  ranges = [
    {
      lower_limit = {row_index = 10};
      upper_limit = {row_index = 20}
    }
  ]
```

Существует [команда](https://ytsaurus.tech/docs/ru/api/commands.md#parse_ypath) `parse_ypath` драйвера, позволяющая канонизировать сложный YPath.

## Поддерживаемые атрибуты { #known_attributes }

[Сложный YPath](#rich_ypath) может быть проаннотирован произвольными атрибутами, что дает возможность расширения. В таблице представлен список атрибутов, которые поддерживает система.

| **Атрибут**         | **Тип**                       | **Описание**                                                 |
| ------------------- | ----------------------------- | ------------------------------------------------------------ |
| `append`            | `bool`                        | Распознается командами записи данных (`write_table`, `write_file`, `upload_parquet` и `upload_orc`) и означает, что новые данные дописываются в конец существующих, а не перезаписывают их. Также распознается на выходных путях таблиц в спецификациях всех операций планировщика и имеет аналогичную семантику. |
| `sorted_by`         | `array<string>`               | Распознается командой записи табличных данных ( `write_table`). При указании этого атрибута пользователь обещает, что записываемые данные упорядочены по указанному набору колонок. Система проверяет это свойство. Ключи должны идти в порядке неубывания, а в случае записи с добавлением проверяется также, что первый записываемый ключ не меньше последнего уже существующего. Атрибут также распознается системой на выходных путях таблиц в спецификациях всех операций планировщика и имеет там аналогичную семантику. В последнем случае также дополнительно требуется, чтобы диапазоны ключей, порождаемые различными джобами, не имели пересечения по внутренней точке, пересечения по границам разрешаются. |
| `ranges`            | `array<ReadRange>`            | Распознается командами чтения данных (`read_table` и `read_file`) и задает список читаемых диапазонов. Если отсутствует, читаются данные целиком. Также распознается на входных путях таблиц в спецификациях всех операций планировщика. Описание структуры словаря `ReadRange` представлено в таблице ниже.|
| `columns`           | `array<string>`               | Распознается командой чтения табличных данных ( `read_table` ) и задает список имен читаемых колонок. Если отсутствует, то читаются все колонки. Также распознается на входных путях таблиц в спецификациях всех операций планировщика. |
| `optimize_for`      | `string`                      | Устанавливает формат хранения для создаваемой таблицы. Атрибут можно указывать c командой `write_table` и на выходных путях операций. Данный атрибут **не совместим** с `<append=true>`. |
| `compression_codec` | `string`                      | Устанавливает формат сжатия для создаваемой таблицы. Атрибут можно указывать с командами `write_file` , `write_table` и на выходных путях операций. Данный атрибут **несовместим** с `<append=true>`. |
| `erasure_codec`     | `string`                      | Выключает erasure-кодирование для создаваемой таблицы. Атрибут можно указывать с командами `write_file` , `write_table` и на выходных путях операций. Данный атрибут **несовместим** с `<append=true>`. |
| `schema`            | `yson-list` с валидной схемой | Валидирует данные относительно указанной схемы и проставляет данную схему на таблицу по окончании операции. Атрибут можно указывать с командой `write_table` и на выходных путях операций. Данный атрибут **несовместим** с `<append=true>`. |
| `transaction_id`    | `string` вида id              | Указание планировщику, под какой транзакцией необходимо обращаться к входной таблице, если на ней указан данный атрибут. |
| `rename_columns`    | `yson-map`                    | Распознается на входящих путях таблиц. Переименовывает названия колонок согласно маппингу перед подачей таблицы на вход операции. Данный атрибут **несовместим** с `teleport` таблицами. |
| `cluster`           | `string`                      | Распознается на путях входных таблиц. Позволяет читать данные по указанному пути, но с другого кластера.

Атрибут `ranges` указывает, какие диапазоны строк таблицы следует прочитать. Указанные диапазоны будут читаться последовательно, в том порядке, в котором они указаны в атрибутах команды. В частности, если диапазоны пересекаются, то на выходе строки будут повторены соответствующее число раз.

| **Атрибут**   | **Тип**     | **Описание**                                                 |
| ------------- | ----------- | ------------------------------------------------------------ |
| `lower_limit` | `ReadLimit` | Нижняя граница чтения                                        |
| `upper_limit` | `ReadLimit` | Верхняя граница чтения                                       |
| `exact`       | `ReadLimit` | Точное значение границы чтения (не может быть указано вместе с lower_limit или upper_limit) |

За исключением ограничений типа `key_bound` все виды ограничений в `lower_limit` являются включительными, а все виды ограничений в `upper_limit` — исключительными. Включительность или исключительность ограничения типа `key_bound` указывается явно в самом key bound. См. также раздел, посвящённый [срезам по ключам](#key_selectors).

`ReadLimit` описывает отдельную границу чтения. Граница может определяться одним из шести **селекторов**: ключом, ключевым ограничением (key bound), номером строки, номером чанка, номером таблета или байтовым смещением. В границе может быть указано несколько селекторов, при этом они все действуют одновременно, усиливая друг друга.

| **Атрибут** | **Тип** | **Описание**                                         |
| ----------- | ------- | ---------------------------------------------------- |
| `key`       | `list`  | Список значений, образующих ключ (только для сортированных таблиц). См. подробнее в [разделе](#key_selectors) |
| `key_bound` | `list`  | Включительное либо невключительное ограничение на префикс ключа; не может присутствовать в exact-границе. См. подробнее в [разделе](#key_selectors) |
| `row_index` | `int`   | Номер строки (только для таблиц)                     |
| `offset`    | `int`   | Байтовое смещение (только для файлов)                |
| `chunk_index` | `int` | Номер чанка |
| `tablet_index` | `int` | Номер таблета (только для упорядоченных динамических таблиц) |

Поддерживаемые системой YTsaurus YPath атрибуты на путях **файлов**

| **Атрибут**             | **Тип**                       | **Описание**                                                 |
| ----------------------- | ----------------------------- | ------------------------------------------------------------ |
| `file_name`             | `string`                      | Распознается при заказе файла в `sandbox` джоба. Атрибут задает относительный путь, по которому надо положить файл. |
| `executable`            | `bool`                        | Распознается при заказе файла в `sandbox` джоба. Атрибут указывает системе необходимость проставить executable-бит на заказанный файл. |
| `bypass_artifact_cache` | `bool`                        | Распознается при заказе файла в `sandbox` джоба. Атрибут включает прямое скачивание файла в `sandbox` джоба минуя файловый кэш на ноде. |
| `format`                | `string`                      | Распознается при заказе табличного файла в `sandbox` джоба. Атрибут обозначает формат, в котором надо сформатировать таблицу при её скачивании в `sandbox` джоба. |


## Срезы сортированных таблиц по ключам { #key_selectors }

Система поддерживает два вида селекторов по значениям ключевых колонок таблицы, которые внешне напоминают друг друга, но отличаются по поведению. Первый вид является исторически более старым и реализуется селектором `key`, а также возможен для указания в [суффиксе YPath](#rich_ypath_suffix). Второй вид является более новым и реализуется селектору `key_bound`; он доступен только через атрибут `ranges` в префиксе YPath.

В новых приложениях рекомендуется использовать селектор типа `key_bound`, так как он обладает большей прозрачностью в поведении и гибкостью в использовании, хотя и более многословен.

{% note info "Примечание" %}

Напомним, что YTsaurus задаёт некоторый линейный порядок сравнения на всевозможных значениях, которые могут встретиться в таблице. В частности, значения типов int64, uint64, double, boolean внутри каждого из этих типов упорядочены естественным образом, значения типа string упорядочены лексикографически, а два значения разных типов данных сравниваются так, как сравниваются их типы в некотором implementation defined порядке. Например, любой int64 меньше любого uint64, а любой null меньше любого не null (`#`) значения.


Поэтому при сравнении значений всегда обязательно следить за типом данных; в частности, беззнаковые целые числа нужно указывать с суфииксом `u`, а дробные числа с десятичной точкой.

{% endnote %}

### Селектор `key`

Селектор `key` доступен к использованию только для сортированных таблиц, у которых все ключевые колонки отсортированы по возрастанию. Селектор `key` имеет тип "список значений", а его поведение определяется следующим образом.

Рассмотрим множество всевозможных кортежей, состоящих из значений системы типов YTsaurus. Определим на этих кортежах линейный порядок по лексикографическому принципу, например:

`[] < ["a"] < ["a"; 3] < ["a"; 4] < ["b"] < ["b"; 2]`

В таком порядке можно сравнивать между собой два кортежа любой длины. Порядок сравнения определяется тем, как сравниваются первые различающиеся компоненты кортежей, если такие есть; в противном случае меньшим является более короткий кортеж.

Если селектор `key` указан как часть ограничения `lower_limit` (или в качестве нижней границы перед двоеточием в модификаторе выбора строк в суффиксе YPath), то он оставляет из множества всех строк только те, у которых **полный** ключ как кортеж больше либо равен кортежу `key` в смысле порядка сравнения выше. В частности, это означает, что селектор `key` может содержать кортеж, состоящий из меньшего или большего числа значений, чем число ключевых колонок в таблице, и это не нарушает корректности определения.

Если селектор `key` указан как часть ограничения `upper_limit` (или в качестве верхней границы после двоеточия в модификаторе выбора строк в суффиксе YPath), то он оставляет из множества всех строк только те, у которых **полный** ключ как кортеж **строго** меньше кортежа `key`.

Если селектор `key` указан как часть ограничения `exact` (или в качестве единственной границы без двоеточия в модификаторе выбора строк в суффиксе YPath), то он оставляет из множества всех строк только те, у которых полный ключ содержит кортеж `key` в качестве префикса.

#### Примеры

Пусть таблица `//tmp/t` имеет две ключевые колонки и содержит следующие ключи:

```
["a"; 1];
["a"; 3];
["a"; 5];
["b"; 2];
["b"; 4];
["c"; 0];
```

Срез `//tmp/t[(b):]`, он же `<ranges = [{lower_limit = {key = [b]}}]>//tmp/t`:
```
["b"; 2];
["b"; 4];
["c"; 0];
```

Срез `//tmp/t[(b, 2, 56):]` (обратите внимание, что ключ в срезе может иметь больше значений, чем количество ключевых колонок в таблице):
```
["b"; 4];
["c"; 0];
```

Срез `//tmp/t[:(c, 0)]`:
```
["a"; 1];
["a"; 3];
["a"; 5];
["b"; 2];
["b"; 4];
```

Срез `//tmp/t[(b)]`:
```
["b"; 2];
["b"; 4];
```

{% note info "Примечание" %}

Для того, чтобы с использованием селектора типа `key` получить исключительную нижнюю границу или включительную верхнюю, необходимо вместо соответствующего кортежа указывать его последователя (successor) в смысле линейного порядка, определённого на кортежах выше, что в общем случае может быть непростой задачей. Данное обстоятельство послужило мотивацией для появления селектора типа `key_bound`, который обсуждается в следующем разделе.

{% endnote %}

### Селектор `key_bound`

Селектор `key_bound` доступен к использованию в сортированных таблицах, ключевые колонки которых могут быть сортированы как по убыванию, так и по возрастанию. Значение селектора типа `key_bound` имеет вид списка, состоящего из двух значений, первое из которых задаёт **отношение** и представляется одной из четырёх строк `">", ">=", "<", "<="`, а второе задаёт **префикс** ключа и является списком значений. Отношения `>` и `>=` могут встречаться только в ограничении `lower_limit`, а `<` и `<=` только в ограничении `upper_limit`; в ограничении `exact` селекторы типа `key_bound` не допускаются.

Примеры селекторов типа `key_bound`:
- `[">"; ["a"; 3]]`
- `["<="; ["b"]]`
- `[">="; []]`

Семантика данного селектора следующая. Рассмотрим таблицу, содержащую `N` ключевых колонок, а также некоторый key bound. Пусть длина префикса ключа в key bound равна `K`. Для использования key bound в применении к данной таблице, `K` должно находиться в пределах 0 до `N`; попытка указать более длинный префикс в key bound приведёт к ошибке.

Для того, чтобы понять, подходит ли строка с некоторым ключом под селектор, необходимо оставить от ключа префикс длины `K`, и сравнить результат с префиксом ключа из key bound лексикографически. Если результат сравнения соответствует указанному отношению, то строка попадает в результат, в противном случае нет.

{% note info "Примечание" %}

Если некоторая колонка является ключевой и отсортирована в обратном порядке (`sort_order = descending`), то результаты всех сравнений соответствующей компоненты кортежа ключа инвертируются; в частности, будут верны соотношения `5u < 2u` и `"foo" < #`.

Также обратите внимание, что в определении поведения селектора `key_bound` сравниваются только кортежи одинаковой длины `K`, поэтому вопрос определения сравнения кортежей разной длины в присутствии обратного порядка сортировки не возникает.

{% endnote %}

В частности, по определению выше селекторы `[">="; []]`, `["<="; []]` допускают любую строку (так как после оставления префикса ключа длины 0 получается кортеж `[]`), а селекторы `[">"; []]`, `["<"; []]` не допускают никакую строку.

#### Примеры

Рассмотрим таблицу `//tmp/t` с теми же ключами, что и в примере выше:
```
["a"; 1];
["a"; 3];
["a"; 5];
["b"; 2];
["b"; 4];
["c"; 0];
```

Срез `<ranges = [{lower_limit = {key_bound = [">"; ["a"; 3]]}}]>//tmp/t`:
```
["a"; 5];
["b"; 2];
["b"; 4];
["c"; 0];
```

Срез `<ranges = [{upper_limit = {key_bound = ["<="; ["b"]]}}]>//tmp/t`:
```
["a"; 1];
["a"; 3];
["a"; 5];
["b"; 2];
["b"; 4];
```

{% note info "Примечание" %}

Обратите внимание, что несмотря на то, что кортеж `["b"; 2]` лексикографически превосходит кортеж `["b"]`, ключ `["b"; 2]` при усечении до длины 1 превращается в кортеж `["b"]`, и поэтому он допускается key bound `["<="; ["b"]]`. Это отличает поведение селектора `key_bound` в от селектора `key`, и расширяет возможности первого по сравнению со вторым, так как с помощью селектора `key` задать аналогичный срез нетривиально.

{% endnote %}

Срез `<ranges = [{lower_limits = {key_bound = [">="; ["b"; 2; 56]]}}]>//tmp/t` не является допустимым, и его использованием приведёт к ошибке `Key bound length must not exceed schema key prefix length`.
<!-- endsource: ru/_includes/user-guide/storage/ypath.md -->