# Фильтры

## WHERE

`WHERE` — это SQL-клауза, которая работает как для полнотекстового поиска, так и для дополнительной фильтрации. Доступны следующие операторы:

* [Операторы сравнения](../Searching/Expressions.md#Comparison-operators) `<, >, <=, >=, =, <>, BETWEEN, IN, IS NULL`
* [Логические операторы](../Searching/Full_text_matching/Operators.md#Boolean-operators) `AND, OR, NOT`

Поддерживается `MATCH('query')`, который соответствует [полнотекстовому запросу](../Searching/Full_text_matching/Operators.md).

Поддерживается синтаксис условия `{col_name | expr_alias} [NOT] IN @uservar`. Описание глобальных пользовательских переменных см. в синтаксисе [SET](../Server_settings/Setting_variables_online.md#SET).

## HTTP JSON

Если вы предпочитаете интерфейс HTTP JSON, вы также можете применять фильтрацию. Он может показаться более сложным, чем SQL, но рекомендуется для случаев, когда вам нужно программно подготовить запрос, например, когда пользователь заполняет форму в вашем приложении.

<!-- example json1 -->
Вот пример нескольких фильтров в запросе `bool`.

Этот полнотекстовый запрос соответствует всем документам, содержащим `product` в любом поле. Эти документы должны иметь цену больше или равную 500 (`gte`) и меньше или равную 1000 (`lte`). Все эти документы не должны иметь ревизию меньше 15 (`lt`).

<!-- request JSON -->
```json
POST /search
{
  "table": "test1",
  "query": {
    "bool": {
      "must": [
        { "match" : { "_all" : "product" } },
        { "range": { "price": { "gte": 500, "lte": 1000 } } }
      ],
      "must_not": {
        "range": { "revision": { "lt": 15 } }
      }
    }
  }
}
```
<!-- end -->


### bool запрос

<!-- example bool -->
Запрос `bool` сопоставляет документы на основе логических комбинаций других запросов и/или фильтров. Запросы и фильтры должны быть указаны в разделах `must`, `should` или `must_not` и могут быть [вложенными](../Searching/Filters.md#Nested-bool-query).

<!-- request JSON -->
```json
POST /search
{
  "table":"test1",
  "query": {
    "bool": {
      "must": [
        { "match": {"_all":"keyword"} },
        { "range": { "revision": { "gte": 14 } } }
      ]
    }
  }
}
```
<!-- end -->

<!-- example must_not -->
### must
Запросы и фильтры, указанные в разделе `must`, должны соответствовать документам. Если указано несколько полнотекстовых запросов или фильтров, все они должны соответствовать. Это эквивалентно запросам `AND` в SQL. Обратите внимание, что если вы хотите сопоставить с массивом ([многозначный атрибут](../Creating_a_table/Data_types.md#Multi-value-integer-%28MVA%29)), вы можете указать атрибут несколько раз. Результат будет положительным только если все запрошенные значения найдены в массиве, например:

```json
"must": [
  {"equals" : { "product_codes": 5 }},
  {"equals" : { "product_codes": 6 }}
]
```

Также обратите внимание, что с точки зрения производительности может быть лучше использовать:
```json
  {"in" : { "all(product_codes)": [5,6] }}
```
(подробности ниже).

### should
Запросы и фильтры, указанные в разделе `should`, должны соответствовать документам. Если некоторые запросы указаны в `must` или `must_not`, запросы `should` игнорируются. С другой стороны, если нет других запросов, кроме `should`, то хотя бы один из этих запросов должен соответствовать документу, чтобы он соответствовал bool-запросу. Это эквивалент запросов `OR`. Обратите внимание, если вы хотите сопоставить с массивом ([многозначный атрибут](../Creating_a_table/Data_types.md#Multi-value-integer-%28MVA%29)) вы можете указать атрибут несколько раз, например:

```json
"should": [
  {"equals" : { "product_codes": 7 }},
  {"equals" : { "product_codes": 8 }}
]
```

Также обратите внимание, что с точки зрения производительности может быть лучше использовать:
```json
  {"in" : { "any(product_codes)": [7,8] }}
```
(подробности ниже).

### must_not
Запросы и фильтры, указанные в разделе `must_not`, не должны соответствовать документам. Если несколько запросов указано в `must_not`, документ соответствует, если ни один из них не соответствует.

<!-- request JSON -->
```json
POST /search
{
  "table":"t",
  "query": {
    "bool": {
      "should": [
        {
          "equals": {
            "b": 1
          }
        },
        {
          "equals": {
            "b": 3
          }
        }
      ],
      "must": [
        {
          "equals": {
            "a": 1
          }
        }
      ],
      "must_not": {
        "equals": {
          "b": 2
        }
      }
    }
  }
}
```
<!-- end -->

### Вложенный bool запрос

<!-- example eq_and_or -->
Bool-запрос может быть вложен в другой bool-запрос, чтобы вы могли создавать более сложные запросы. Чтобы сделать вложенный логический запрос, просто используйте другой `bool` вместо `must`, `should` или `must_not`. Вот как этот запрос:

```
a = 2 and (a = 10 or b = 0)
```

должен быть представлен в JSON.

<!-- request JSON -->
a = 2 and (a = 10 or b = 0)

```json
POST /search
{
  "table":"t",
  "query": {
    "bool": {
      "must": [
        {
          "equals": {
            "a": 2
          }
        },
        {
          "bool": {
            "should": [
              {
                "equals": {
                  "a": 10
                }
              },
              {
                "equals": {
                  "b": 0
                }
              }
            ]
          }
        }
      ]
    }
  }
}
```
<!-- end -->

<!-- example complex -->
Более сложный запрос:
```
(a = 1 and b = 1) or (a = 10 and b = 2) or (b = 0)
```
<!-- request JSON -->

(a = 1 and b = 1) or (a = 10 and b = 2) or (b = 0)

```json
POST /search
{
  "table":"t",
  "query": {
    "bool": {
      "should": [
        {
          "bool": {
            "must": [
              {
                "equals": {
                  "a": 1
                }
              },
              {
                "equals": {
                  "b": 1
                }
              }
            ]
          }
        },
        {
          "bool": {
            "must": [
              {
                "equals": {
                  "a": 10
                }
              },
              {
                "equals": {
                  "b": 2
                }
              }
            ]
          }
        },
        {
          "bool": {
            "must": [
              {
                "equals": {
                  "b": 0
                }
              }
            ]
          }

        }
      ]
    }
  }
}
```
<!-- end -->

### Запросы в формате SQL
<!-- example query_string -->
Запросы в формате SQL (`query_string`) также могут использоваться в bool-запросах.

<!-- request JSON -->
```json
POST /search
{
  "table": "test1",
  "query": {
    "bool": {
      "must": [
        { "query_string" : "product" },
        { "query_string" : "good" }
      ]
    }
  }
}
```
<!-- end -->

## Различные фильтры

### Фильтры равенства
<!-- example equals -->
Фильтры равенства — это простейшие фильтры, которые работают с целочисленными, вещественными и строковыми атрибутами.

<!-- request JSON -->
```json
POST /search
{
  "table":"test1",
  "query": {
    "equals": { "price": 500 }
  }
}
```
<!-- end -->

<!-- example equals_any -->
Фильтр `equals` может быть применен к [многозначному атрибуту](../Creating_a_table/Data_types.md#Multi-value-integer-%28MVA%29) и вы можете использовать:
* `any()`, который будет положительным, если атрибут имеет хотя бы одно значение, равное запрошенному;
* `all()`, который будет положительным, если атрибут имеет единственное значение и оно равно запрошенному

<!-- request JSON -->
```json
POST /search
{
  "table":"test1",
  "query": {
    "equals": { "any(price)": 100 }
  }
}
```
<!-- end -->


### Фильтры множества
<!-- example set -->
Фильтры множества проверяют, равно ли значение атрибута любому из значений в указанном множестве.

Фильтры множества поддерживают целочисленные, строковые и многозначные атрибуты.

<!-- request JSON -->
```json
POST /search
{
  "table":"test1",
  "query": {
    "in": {
      "price": [1,10,100]
    }
  }
}
```
<!-- end -->

<!-- example set_any -->
При применении к [многозначному атрибуту](../Creating_a_table/Data_types.md#Multi-value-integer-%28MVA%29) вы можете использовать:
* `any()` (эквивалентно отсутствию функции), который будет положительным, если есть хотя бы одно совпадение между значениями атрибута и запрошенными значениями;
* `all()`, который будет положительным, если все значения атрибута находятся в запрошенном множестве

<!-- request JSON -->
```json
POST /search
{
  "table":"test1",
  "query": {
    "in": {
      "all(price)": [1,10]
    }
  }
}
```
<!-- end -->

### Фильтры диапазона
<!-- example range -->
Фильтры диапазона сопоставляют документы, у которых значения атрибутов находятся в указанном диапазоне.

Фильтры диапазона поддерживают следующие свойства:
* `gte`: больше или равно
* `gt`: больше
* `lte`: меньше или равно
* `lt`: меньше

<!-- request JSON -->
```json
POST /search
{
  "table":"test1",
  "query": {
    "range": {
      "price": {
        "gte": 500,
        "lte": 1000
      }
    }
  }
}
```
<!-- end -->

### Фильтры географического расстояния

<!-- example geo -->
Фильтры `geo_distance` используются для фильтрации документов, которые находятся в пределах определенного расстояния от географического местоположения.

##### location_anchor
Указывает точку привязки, в градусах. Расстояния рассчитываются от этой точки.

##### location_source
Указывает атрибуты, содержащие широту и долготу.

##### distance_type
Указывает функцию расчета расстояния. Может быть adaptive или haversine. adaptive быстрее и точнее, подробности см. в `GEODIST()`. Необязательный параметр, по умолчанию adaptive.

##### distance
Определяет максимальное расстояние от местоположения точек привязки. Все документы в пределах этого расстояния считаются соответствующими. Расстояние может быть указано в различных единицах измерения. Если единица измерения не указана, расстояние считается в метрах. Вот список поддерживаемых единиц измерения расстояния:

* Метр: `m` или `meters`
* Километр: `km` или `kilometers`
* Сантиметр: `cm` или `centimeters`
* Миллиметр: `mm` или `millimeters`
* Миля: `mi` или `miles`
* Ярд: `yd` или `yards`
* Фут: `ft` или `feet`
* Дюйм: `in` или `inch`
* Морская миля: `NM`, `nmi` или `nauticalmiles`

Свойства `location_anchor` и `location_source` принимают следующие форматы широты/долготы:

* объект с ключами lat и lon: `{ "lat": "attr_lat", "lon": "attr_lon" }`
* строка следующей структуры: `"attr_lat, attr_lon"`
* массив с широтой и долготой в следующем порядке: `[attr_lon, attr_lat]`

Широта и долгота указываются в градусах.


<!-- request Basic example -->
```json
POST /search
{
  "table":"test",
  "query": {
    "geo_distance": {
      "location_anchor": {"lat":49, "lon":15},
      "location_source": {"attr_lat, attr_lon"},
      "distance_type": "adaptive",
      "distance":"100 km"
    }
  }
}
```

<!-- request Advanced example -->
`geo_distance` может использоваться в качестве фильтра в bool-запросах вместе с matches или другими фильтрами атрибутов.

```json
POST /search
{
  "table": "geodemo",
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "*": "station"
          }
        },
        {
          "equals": {
            "state_code": "ENG"
          }
        },
        {
          "geo_distance": {
            "distance_type": "adaptive",
            "location_anchor": {
              "lat": 52.396,
              "lon": -1.774
            },
            "location_source": "latitude_deg,longitude_deg",
            "distance": "10000 m"
          }
        }
      ]
    }
  }
}
```

<!-- end -->
<!-- proofread -->

