Атомарные функции
Reindexer предоставляет встроенные функции, которые могут использоваться в условиях WHERE для расширенных возможностей фильтрации, выходящих за рамки простых сравнений полей.
Внимание
В настоящий момент использование разных функций из данного раздела в одном условии не поддерживается. При этом внутри одного запроса общее количество функций может быть любым.
Определение текущего времени
Функция now() возвращает текущую отметку времени системы, что может быть удобно для фильтрации по времени и синхронизации данных. Функция применяется как в SELECT-, так и в UPDATE-запросах.
Функция принимает опциональный параметр, который определяет точность возвращаемого значения:
sec— секунды (по умолчанию, если параметр не передан);msec— миллисекунды;usec— микросекунды;nsec— наносекунды.
Найти записи с записи с текущей отметкой времени в секундах:
query := db.Query("items").
WhereExpressions(
reindexer.Field{Name: "created_at"},
reindexer.EQ,
reindexer.Now{TimeUnit: reindexer.Sec}
)
query = (
db.new_query("items").
where_expressions(Field("created_at"), CondType.CondEq, Now(TimeUnit.SEC))
)
query.execute()
Внимание
На данный момент в Java нет нативной поддержки фильтрующих функций, поэтому использовать их возможно только через SQL.
ResultIterator<Item> query = db.execSql(
"SELECT * FROM items WHERE created_at = now()",
Item.class
);
SELECT * FROM items WHERE created_at = now()
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": [
{
"cond": "eq",
"right_expression": {
"type": "expression",
"value": "now()"
},
"left_expression": {
"type": "field",
"value": "created_at"
}
}
]
}
'
Добавление текущей отметки времени в микросекундах в наносекундах в поле updated_at при обновлении записи:
query := db.Query("items").
Where("id", reindexer.EQ, 1).
SetExpression("updated_at", "now(usec)").
Update()
query = (
db.new_query("items").
where("id", CondType.CondEq, 1).
expression("updated_at", "now(usec)")
)
query.update()
UPDATE items SET updated_at = now(usec) WHERE id = 1
curl \
--location \
--request PUT \
http://127.0.0.1:9088/api/v1/db/testdb/query \
--header 'Content-Type: application/json' \
--data-raw \
'
{
"namespace": "items",
"type": "update",
"filters": [
{
"cond": "eq",
"field": "id",
"value": 1
}
],
"update_fields": [
{
"name": "updated_at",
"type": "expression",
"values": [
"now(usec)"
]
}
]
}
'
Примечания:
- Все вызовы
now()возвращает одну и ту же метку Unix-времени, которая вычисляется один раз в начале выполнения запроса. - В WHERE-выражениях
now()всегда располагается справа от оператора сравнения, при этом обязательным условием является наличие имени поля.
Вычисление размера полей
Функция flat_array_len() возвращает длину или кардинальность указанного поля, что делает её полезной для фильтрации на основе размеров массивов или наличия полей. Применяется только в SELECT-запросах.
Поведение в зависимости от типа поля:
- Массивы: возвращает количество элементов в массиве.
- Скалярные поля (целые числа, строки и т. д.): всегда возвращает
1. - Объекты: всегда возвращает
1. - Вложенные элементы массивов: возвращает количество вхождений, когда поле находится внутри массивов.
Поиск постов в соцсетях с количеством комментариев от 10 до 50 и хотя бы 3 прикрепленными медиафайлами:
query := db.Query("posts").
WhereFlatArrayLen("comment", reindexer.GE, 10).
WhereFlatArrayLen("comment", reindexer.LE, 50).
WhereFlatArrayLen("media", reindexer.GE, 3)
it := query.Exec()
query = (
db.new_query("posts").
where_expressions(FlatArrayLen("comment"), CondType.CondGe, Values(10)).
where_expressions(FlatArrayLen("comment"), CondType.CondLe, Values(50)).
where_expressions(FlatArrayLen("media"), CondType.CondGe, Values(3))
)
query.execute()
Внимание
На данный момент в Java нет нативной поддержки фильтрующих функций, поэтому использовать их возможно только через SQL.
ResultIterator<Item> query = db.execSql(
"SELECT * FROM posts WHERE flat_array_len(comments) RANGE(10, 50) and flat_array_len(media) >= 3",
Item.class
);
SELECT * FROM posts WHERE flat_array_len(comments) RANGE(10, 50) AND flat_array_len(media) >= 3
curl \
--location \
--request POST \
http://127.0.0.1:9088/api/v1/db/testdb/query \
--header 'Content-Type: application/json' \
--data-raw \
'
{
"namespace": "posts",
"type": "select",
"filters": [
{
"op": "and",
"cond": "range",
"left_expression": {
"type": "expression",
"value": "flat_array_len(comments)"
},
"right_expression": {
"type": "values",
"value": [
10,
50
]
}
},
{
"op": "and",
"cond": "ge",
"left_expression": {
"type": "expression",
"value": "flat_array_len(media)"
},
"right_expression": {
"type": "values",
"value": [
3
]
}
}
]
}
'
Обновления записи с применением flat_array_len():
res, err := db.Query("items").
Where("id", reindexer.EQ, 1).
SetExpression("size", "flat_array_len(comments)").
Update().
FetchAll()
query = (
db.new_query("items").
where("id", CondType.CondEq, 1).
expression("size", "flat_array_len(comments)")
)
query.update()
Внимание
На данный момент в Java нет нативной поддержки фильтрующих функций, поэтому использовать их возможно только через SQL.
ResultIterator<Item> query = db.execSql(
"UPDATE items SET size = flat_array_len(comments) where id = 1",
Item.class
);
UPDATE items SET size = flat_array_len(comments) where id = 1
curl \
--location \
--request PUT \
http://127.0.0.1:9088/api/v1/db/testdb/query \
--header 'Content-Type: application/json' \
--data-raw \
'
{
"namespace": "items",
"type": "update",
"filters": [
{
"cond": "eq",
"field": "id",
"value": 1
}
],
"update_fields": [
{
"name": "size",
"type": "expression",
"values": [
"flat_array_len(comments)"
]
}
]
}
'
Примечания:
- Функция
flat_array_len()эффективно работает с индексированными полями. - Возвращает
0, если указанное поле не существует в документе. Для скалярных индексных полей, не отмеченных какsparse, результат функции будет равен1, даже если поле явным образом не указано в документе. - Поддерживает следующие операторы сравнения:
=,>,>=,<,<=,Range,Set. - В WHERE-выражениях с операторами сравнения
flat_array_len()всегда располагается слева от оператора.