Простая выборка данных и выборка с условием
Простая выборка данных
Простая выборка используется для поиска и вывода данных из неймспейса БД без условий. Пример:
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]}} |
- |