Простая выборка данных и выборка с условием
Простая выборка данных
Простая выборка используется для поиска и вывода данных из неймспейса БД без условий. Пример:
query := db.Query("test_namespace")
SELECT * FROM test_namespace
curl --location --request POST 'http://127.0.0.1:9088/api/v1/db/testdb/query' \
--header 'Content-Type: application/json' \
--data-raw '{
"namespace": "test_namespace",
"type": "select"
}'
Простая выборка данных с фильтрацией полей
Используя Query.Select() в go, перечисление в SELECT-секции (SELECT field1, field2, field3 from ns) в sql и select_filter в JSON при HTTP-запросах,
можно управлять тем, какие поля документов будут возвращены в результате выполнения запроса.
При перечислении полей требуется указывать существующие в документах JSON-пути с учётом их регистра.
Несуществующие поля или поля с неправильным регистром игнорируются.
Если в этом списке нет полей, удовлетворяющих данным условиям, то фильтрация не применяется, и в результате выполнения запроса будут возвращены все поля документов.
Пример:
Пусть структура документа определена следующим образом:
type Item struct {
ID int64 `reindex:"id,,pk"`
Name string `json:"author_name" reindex:"name"`
Articles []int `reindex:"articles"`
Year int `reindex:"year,tree"`
}
Тогда корректный запрос с фильтрацией полей id и name выглядит следующим образом:
query := db.Query("test_namespace").Select ("ID", "author_name")
SELECT ID, author_name FROM test_namespace
curl --location --request POST 'http://127.0.0.1:9088/api/v1/db/testdb/query' \
--header 'Content-Type: application/json' \
--data-raw '{
"namespace": "test_namespace",
"select_filter": [
"ID",
"author_name"
],
"type": "select"
}'
Выборка данных с условиями
Для выборки данных с условиям в Reindexer совместно с оператором SELECT используется ключевое слово WHERE.
Можно использовать выражения с общими операторами сравнения (в SQL-запросах) и операторами сравнения значений (при взаимодействии с БД через коннекторы):
В SQL-запросах на выборку данных можно использовать следующие операторы:
| Оператор | Описание/пояснение |
|---|---|
= |
Равно |
> |
Больше |
< |
Меньше |
>= |
Больше или равно |
<= |
Меньше или равно |
<> |
Не равно |
IN |
Определяет набор значений, с которым будут сравниваться результаты при выборке |
RANGE |
Определяет диапазон значений, которые будут использоваться при выборке |
LIKE |
Поиск по заданному шаблону. Подробнее об операторе – в разделе Простой поиск |
IS NULL |
Значение не задано |
IS NOT NULL |
Задано какое-либо значение |
ST_DWithin |
Получение объектов, находящихся на определенном расстоянии от других объектов (только для геометрического типа данных) |
В запросах на выборку данных при взаимодействии с Reindexer через Go-коннектор можно использовать следующие операторы и методы:
| Оператор | Описание/пояснение |
|---|---|
EQ |
Равно |
GT |
Больше |
LT |
Меньше |
GE |
Больше или равно |
LE |
Меньше или равно |
SET |
Проверяет значение в наборе значений, разделенных запятыми, и извлекает соответствующие строки из неймспейса. Также позволяет проверить, есть ли у массивов общие элементы |
ALLSET |
Проверяет значение в наборе значений, разделенных запятыми, и извлекает соответствующие строки из неймспейса. Также позволяет проверить, есть ли у массивов общие элементы, при этом все элементы первого массива должны входить во второй |
RANGE |
Определяет диапазон значений, которые будут использоваться при выборке |
ANY |
Любое значение |
EMPTY |
Пустое значение (в том числе и массив нулевой длины) |
LIKE |
Поиск по заданному шаблону. Подробнее об операторе – в разделе Простой поиск |
ST_DWithin() |
Получение объектов, находящихся на определенном расстоянии от других объектов (только для геометрического типа данных) |
Match() |
Запросы к полнотекстовым индексам. Подробнее — в разделе Запросы к полнотекстовым индексам |
Not() |
Логическое отрицание для любого следующего оператора |
Условия можно комбинировать с помощью логических операторов OR и AND.
При этом операции с
ORимеют более высокий приоритет, чемAND. Например, условие видаWHERE a AND b OR c AND dэквивалентноWHERE a AND (b OR c) AND d.
Также Reindexer поддерживает условия с фильтрацией при помощи сравнения полей одного и того же документа.
Пример запроса с одним условием:
query := db.Query("test_namespace").
Where("year", reindexer.EQ, 2022)
SELECT * FROM test_namespace WHERE year = 2022
curl --location --request POST 'http://127.0.0.1:9088/api/v1/db/testdb/query' \
--header 'Content-Type: application/json' \
--data-raw '{
"namespace": "test_namespace",
"type": "select",
"filters": [
{
"field": "year",
"cond": "EQ",
"value": 2022
}
]
}'
Пример запроса с несколькими условиями:
query := db.Query("test_namespace").
Where("year", reindexer.QE, 2022).
Where("price", reindexer.LE, 1000)
SELECT * FROM test_namespace WHERE year = 2022 AND price <= 1000
curl --location --request POST 'http://127.0.0.1:9088/api/v1/db/testdb/query' \
--header 'Content-Type: application/json' \
--data-raw '{
"namespace": "test_namespace",
"type": "select",
"filters": [
{
"field": "year",
"cond": "EQ",
"value": 2022
},
{
"field": "price",
"cond": "LE",
"value": 1000
}
]
}'
Приоритет операций может быть изменён при помощи использования скобок. Механизм задания скобок зависит от конкретного API:
query := db.Query("test_namespace").
OpenBracket().
Where("year", reindexer.EQ, 2022).
Where("price", reindexer.LE, 1000).
CloseBracket().
Or().
OpenBracket().
Where("year", reindexer.EQ, 2010).
Where("price", reindexer.GT, 2000).
CloseBracket()
SELECT * FROM test_namespace WHERE (year = 2022 AND price <= 1000) OR (year = 2010 AND price > 2000)
curl --location --request POST 'http://127.0.0.1:9088/api/v1/db/testdb/query' \
--header 'Content-Type: application/json' \
--data-raw '{
"namespace": "test_namespace",
"type": "select",
"filters": [
{
"filters": [
{
"field": "year",
"cond": "EQ",
"value": 2022
},
{
"field": "price",
"cond": "LE",
"value": 1000
}
]
},
{
"op": "OR",
"filters": [
{
"field": "year",
"cond": "EQ",
"value": 2010
},
{
"field": "price",
"cond": "GT",
"value": 2000
}
]
}
]
}'
Пример запроса с использованием условного оператора LIKE:
query := db.Query("test_namespace").
Where("field_description", reindexer.LIKE, "info%")
SELECT * FROM test_namespace WHERE field_description LIKE 'info%'
curl --location --request POST 'http://127.0.0.1:9088/api/v1/db/testdb/query' \
--header 'Content-Type: application/json' \
--data-raw '{
"namespace": "test_namespace",
"type": "select",
"filters": [
{
"field": "name",
"cond": "LIKE",
"value": "info%"
}
]
}'
LIKEиспользует метод полного сканирования поля и его применение ведет к увеличению нагрузки на сервер. Для полнотекстового поиска с высокой скоростью рекомендуется использовать полнотекстовые индексы.
Пример запроса с фильтрацией при помощи сравнения полей одного и того же документа:
В Go-коннекторе для запросов с фильтрацией при помощи сравнения полей одного и того документа используется метод WhereBetweenFields().
query := db.Query("test_namespace").
WhereBetweenFields("price", reindexer.GE, "recommended_price")
В SQL-запросах имена индексов (полей неймспейсов) должны быть указаны в двойных кавычках. При указании в одинарных кавычках они будут восприниматься как строки.
SELECT * FROM test_namespace WHERE "recommended_price" > "price"
curl --location --request POST 'http://127.0.0.1:9088/api/v1/db/testdb/query' \
--header 'Content-Type: application/json' \
--data-raw '{
"namespace": "test_namespace",
"type": "select",
"filters": [
{
"first_field": "recommended_price",
"cond": "LE",
"second_field": "price"
}
]
}'
Пример запроса для выборки из композитного индекса:
query := db.Query("test_namespace").WhereComposite("price+year", reindexer.EQ,[]interface{}{10000,2022})
Имя композитного индекса необходимо передавать в кавычках, а требуемые значения — в фигурных скобках.
SELECT * FROM test_namespace WHERE "price+year" = {10000, 2022}
Особенности поиска по условию IS NULL
- Фильтрация по
IS NULLдопустима только дляsparse-индексов, массивов, векторных индексов и неиндексных полей; - Условие
f = NULLбудет заменено планировщиком наf IS NULL; - Условие
f IN (1, 2, 3, NULL)будет заменено планировщиком наf IN (1, 2, 3) OR f IS NULL; - Условие
f ALLSET (1, 2, 3, NULL)будет заменено планировщиком наf ALLSET (1, 2, 3) AND f IS NULL; - Для остальных условий c аргументом NULL (например
f > NULL) будет возвращена ошибка.
Результаты запросов по условию IS NULL в зависимости от значения поля в документе:
+- документ будет в выдаче;-- документа не будет в выдаче;n- невозможно создать такой документ.
Поле без вложенности. В индексе задан json_paths: ["f"] или json_paths: ["obj"] в зависимости от контекста:
| Документ | Неиндексное | Массив | Sparse | Sparse массив |
|---|---|---|---|---|
{} |
+ | + | + | + |
{"f": null} |
+ | + | + | + |
{"f": []} |
+ | + | + | + |
{"f": [null]} |
+ | - | + | + |
{"f": [1, null]} |
+ | - | + | + |
{"f": 0} |
- | - | - | - |
{"f": [0]} |
- | - | - | - |
{"obj": {}} |
- | n | - | - |
{"obj": {"f": null}} |
- | n | - | - |
{"obj": {"f": null, "a": 0}} |
- | n | - | - |
Поле без вложенности. В индексе задан json_paths: ["f1", "f2"] или json_paths: ["obj1", "obj2"] в зависимости от
контекста:
| Документы | Массив с несколькими json путями |
|---|---|
{}, {} |
+ |
{"f1": 1}, {} |
- |
{"f1": null}, {"f2": null} |
+ |
{"f1": 1}, {"f2": null} |
- |
{"f1": []}, {"f2": []} |
+ |
{"f1": [1]}, {"f2": []} |
- |
{"f1": [null]}, {"f2": [null]} |
- |
{"f1": [1, null]}, {"f2": [1, null]} |
- |
{"f1": 0}, {"f2": 0} |
- |
{"f1": [0]}, {"f2": [0]} |
- |
{"obj1": {}}, {"obj2": {}} |
n |
{"obj1": {"f": null}}, {"obj2": {"f": null}} |
n |
{"obj1": {"f": null, "a": 0}}, {"obj2": {"f": null, "a": 0}} |
n |
Поле со вложенностью. В индексе задан json_paths: ["obj.f"]:
| Документ | Массив | Sparse | Sparse массив |
|---|---|---|---|
{"obj": {}} |
+ | + | + |
{"obj": {"f": null}} |
+ | + | + |
{"obj": {"f": null, "a": 0}} |
+ | + | + |
{"obj": {"f": [null]}} |
- | n | + |
{"obj": {"f": [1, null]}} |
- | n | + |
Поле со вложенностью. В индексе задан json_paths: ["obj1.f", "obj2.f"]:
| Документы | Массив с несколькими json путями |
|---|---|
{"obj1": {}}, {"obj2": {}} |
+ |
{"obj1": {"f": 1}}, {"obj2": {}} |
- |
{"obj1": {"f": null}}, {"obj2": {"f": null}} |
+ |
{"obj1": {"f": 1}}, {"obj2": {"f": null}} |
- |
{"obj1": {"f": null, "a": 0}}, {"obj2": {"f": null, "a": 0}} |
+ |
{"obj1": {"f": 1, "a": 0}}, {"obj2": {"f": null, "a": 0}} |
- |
{"obj1": {"f": [null]}}, {"obj2": {"f": [null]}} |
- |
{"obj1": {"f": [1, null]}}, {"obj2": {"f": [1, null]}} |
- |