Запросы для обновления и удаления данных
Запросы для обновления (UPDATE) и удаления (DELETE) применяются в Reindexer для выполнения следующих операций:
- изменение содержимого полей записи или группы записей,
- добавление новых полей,
- удаление неиндексных полей,
- удаление записей.
UPDATE-запросы для изменения и добавления полей записей
В Reindexer используется следующий синтаксис запросов на обновление данных:
db.Query("nsName").Where("field", reindexer.EQ, 40).Set("field1", value1).Set("field2", value2) ... Set("fieldN", valueN).Update()
Кроме того, в одном запросе можно объединить несколько выражений Set... разных типов, например: Set(...).SetExpression(...).SetObject(...)...
UPDATE nsName
SET field1 = value1, field2 = value2, ..
WHERE condition;
curl --location --request PUT 'http://127.0.0.1:9088/api/v1/db/testdb/query' \
--header 'Content-Type: application/json' \
--data-raw '{
"namespace": "items",
"filters": [
{
"Field": "id",
"Cond": "EQ",
"Value": [
2
]
}
],
"update_fields": [
{
"name": "info",
"type": "value",
"is_array": false,
"values": [
"new info"
]
}
]
}'
Изменение типа значения поля при обновлении записи
В Reindexer механизмы обновления полей имеют следующие особенности:
-
При изменении неиндексного поля замена текущего значения на значение другого типа полностью заменяет содержимое поля, устанавливается значение другого типа.
Пример:
Записываем в поле значение типа
int:UPDATE nsName SET newField = 3 WHERE id = 5Обновляем поле, записываем в него значение типа
string:UPDATE nsName SET newField = 'String' WHERE id = 5Запрос выполнится успешно.
-
Значения индексных полей можно преобразовать только в смежный типы. Например,
intв числовую строку вида ‘123456’ и обратно, либоboolв строку вида ’true’ и обратно.Пример:
Обновляем индексное поле с типом значения
int, записываем в него числовую строку:UPDATE nsName SET newField = '123' WHERE id = 5Запрос выполнится успешно.
Обновляем индексное поле с типом значения
int, записываем в него строку:UPDATE nsName SET newField = 'Text' WHERE id = 5Получим ошибку “Can`t convert Text to number”.
-
Изменение значения индексного поля-массива на
nullвозвращает его к значению по умолчанию.
Добавление новых полей к записям в неймспейсах
С помощью UPDATE-запросов возможно добавление новых полей к существующим записям в неймспейсе. Можно добавить поле для одной или нескольких записей.
Пример:
db.Query("items").Where("id", reindexer.GE, 100).Set("newField", "Brand new!").Update()
UPDATE items SET newField = 'Brand new!' WHERE id > 100
curl --location --request PUT 'http://127.0.0.1:9088/api/v1/db/testdb/query' \
--header 'Content-Type: application/json' \
--data-raw '{
"namespace": "items",
"filters": [
{
"Field": "id",
"Cond": "GE",
"Value": [
100
]
}
],
"update_fields": [
{
"name": "newField",
"type": "value",
"is_array": false,
"values": [
"Brand new!"
]
}
]
}'
Добавление вложенных полей с несколькими уровнями вложенности
В Reindexer возможно добавление вложенных полей с несколькими уровнями вложенности.
Пример:
db.Query("items").Where("id", reindexer.GE, 100).Set("nested.nested2.nested3.nested4.newField", "new nested field!").Update()
Код из этого примера добавляет в неймспейс items поле nested с вложенными объектами nested2, nested3, nested4.
В nested4 добавляется поле newField с содержимым new nested field!.
UPDATE items SET nested.nested2.nested3.nested4.newField = 'new nested field!' WHERE id > 100
Код из этого примера добавляет в неймспейс items поле nested с вложенными объектами nested2, nested3, nested4.
В nested4 добавляется поле newField с содержимым new nested field!.
Для добавления вложенных полей при обновлении записей по HTTP значение поля “update_fields” -> “type” в теле запроса должно быть object.
curl --location --request PUT 'http://127.0.0.1:9088/api/v1/db/testdb/query' \
--header 'Content-Type: application/json' \
--data-raw '{
"namespace": "items",
"filters": [
{
"Field": "id",
"Cond": "GE",
"Value": [
100
]
}
],
"update_fields": [
{
"name": "nested",
"type": "object",
"is_array": false,
"values": [
{
"nested2": {
"nested3": {
"nested4": {
"newField": "new nested field!"
}
}
}
}
]
}
]
}'
Код из этого примера добавляет в неймспейс full поле nested с вложенными объектами nested2, nested3, nested4.
В nested4 добавляется поле newField с содержимым new nested field!.
Арифметические выражения в UPDATE-запросах
При выполнении UPDATE-запросов к Reindexer возможно добавление в них арифметических выражений с использованием следующих знаков:
+(сложение),-(вычитание),/(деление),*(умножение),().
Пример запроса на обновление данных в Reindexer с использованием арифметических выражений:
При взаимодействии с Reindexer через Go-коннектор для добавления в запрос арифметических выражений используйте метод
SetExpression().
db.Query("items").Where("field5", reindexer.EQ, 1).SetExpression("field", "field1+field2").Update()
UPDATE items SET field1 = field2+field3-(field4+5)/2 WHERE field5 = 1
Для добавления арифметических выражений при обновлении поля по HTTP значение поля “update_fields” -> “type” в теле запроса должно быть expression.
curl --location --request PUT 'http://127.0.0.1:9088/api/v1/db/testdb/query' \
--header 'Content-Type: application/json' \
--data-raw '{
"namespace": "items",
"filters": [
{
"Field": "id",
"Cond": "EQ",
"Value": [
1
]
}
],
"update_fields": [
{
"name": "field",
"type": "expression",
"is_array": false,
"values": [
"field1 + field2"
]
}
]
}'
Также в UPDATE-запросах можно использовать такие функции, как now(), sec(), serial().
Пример:
При взаимодействии с Reindexer через Go-коннектор для добавления в запрос арифметических выражений и функций используйте метод SetExpression().
db.Query("items").Where("id", reindexer.EQ, 3).SetExpression("field", "field2*now()").Update()
UPDATE items SET field1 = field2*NOW() WHERE id = 3
Для добавления арифметических выражений при обновлении поля по HTTP значение поля “update_fields” -> “type” в теле запроса должно быть expression.
curl --location --request PUT 'http://127.0.0.1:9088/api/v1/db/testdb/query' \
--header 'Content-Type: application/json' \
--data-raw '{
"namespace": "items",
"filters": [
{
"Field": "id",
"Cond": "EQ",
"Value": [
1
]
}
],
"update_fields": [
{
"name": "field",
"type": "expression",
"is_array": false,
"values": [
"field1 * now()"
]
}
]
}'
Обновление полей-массивов
В Reindexer реализован механизм обновления, который позволяет изменять определенный элемент существующего массива или заменять поле-массив целиком.
Примеры:
Изменение элемента массива:
db.Query("items").Where("id", reindexer.EQ, 11).Set("arrayField[0]", 3).Update()
UPDATE items SET arrayField[0] = 3 WHERE id = 1
Для изменения элемента массива по HTTP значение поля “update_fields” -> “type” в теле запроса должно быть value.
curl --location --request PUT 'http://127.0.0.1:9088/api/v1/db/testdb/query' \
--header 'Content-Type: application/json' \
--data-raw '{
"namespace": "items",
"filters": [
{
"Field": "id",
"Cond": "EQ",
"Value": [
11
]
}
],
"update_fields": [
{
"name": "arrayField[0]",
"type": "value",
"is_array": false,
"values": [
3
]
}
]
}'
Обновление всего массива:
db.Query("items").Where("id", reindexer.EQ, 11).Set("arrayField", []int{999, 1999, 2999}).Update()
UPDATE items SET arrayField = [999, 1999, 2999] 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",
"filters": [
{
"Field": "id",
"Cond": "EQ",
"Value": [
11
]
}
],
"update_fields": [
{
"name": "arrayField",
"type": "value",
"is_array": true,
"values": [
999,
1999,
2999
]
}
]
}'
Добавление элементов в начало массива:
Для добавления элементов в начало массива через Go используйте метод SetExpression().
db.Query("items").Where("id", reindexer.EQ, 11).SetExpression("arrayField", "[999, 1999, 2999] || arrayField").Update()
UPDATE items SET arrayField = [999, 1999, 2999] || arrayField WHERE id = 1
Для добавления элементов в начало массива по HTTP значение поля “update_fields” -> “type” в теле запроса должно быть expression.
curl --location --request PUT 'http://127.0.0.1:9088/api/v1/db/testdb/query' \
--header 'Content-Type: application/json' \
--data-raw '{
"namespace": "items",
"filters": [
{
"Field": "id",
"Cond": "EQ",
"Value": [
11
]
}
],
"update_fields": [
{
"name": "arrayField",
"type": "expression",
"is_array": false,
"values": [
"[999, 1999, 2999]||arrayField"
]
}
]
}'
Добавление элементов в конец массива:
Для добавления элементов в конец массива через Go используйте метод SetExpression().
db.Query("items").Where("id", reindexer.EQ, 11).SetExpression("arrayField", "arrayField || [999, 1999, 2999]").Update()
UPDATE items SET arrayField = arrayField || [999, 1999, 2999] WHERE id = 1
Для добавления элементов в конец массива по HTTP значение поля “update_fields” -> “type” в теле запроса должно быть expression.
curl --location --request PUT 'http://127.0.0.1:9088/api/v1/db/testdb/query' \
--header 'Content-Type: application/json' \
--data-raw '{
"namespace": "items",
"filters": [
{
"Field": "id",
"Cond": "EQ",
"Value": [
11
]
}
],
"update_fields": [
{
"name": "arrayField",
"type": "expression",
"is_array": false,
"values": [
"arrayField||[999, 1999, 2999]"
]
}
]
}'
Обновление массивов объектов
Reindexer также позволяет обновлять элементы массивов объектов.
Примеры:
Обновление элемента массива объектов:
Для обновления элемента массива объектов через Go используйте метод SetObject().
db.Query("items").Where("id", reindexer.EQ, 1).SetObject("objectsArray[0]", updatedValue).Update()
UPDATE items SET objectsArray[0] = {"Id":0,"Description":"Updated!"} 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",
"filters": [
{
"Field": "id",
"Cond": "EQ",
"Value": [
1
]
}
],
"update_fields": [
{
"name": "objectsArray[0]",
"type": "object",
"is_array": false,
"values": [
{
"Id": 0,
"Description": "Updated"
}
]
}
]
}'
Обновление индексного Array-поля, находящегося внутри массива объектов:
Пример ниже рассмотрен для неймспейса с именем ns, в котором есть индекс с параметрами: name="nested",json_paths=["nested.field1"] и is_array=true.
ВАЖНО. Для фильтрации (выборки массива объектов) при выполнении таких запросов используйте имя индекса (в примере —
nested). А для изменения значений вложенных полей — их jsonpath (в примере —nested[1].field1).
Исходная запись:
{
"id":1,
"nested":[{"field1": 1, "field2": 2},
{"field1": 3, "field2": 4},
{"field1": 5, "field2": 6}]
}
Запись после обновления индексного Array-поля, находящегося внутри массива объектов:
{
"id":1,
"nested":[{"field1": 1, "field2": 2},
{"field1": 123, "field2": 4},
{"field1": 5, "field2": 6}]
}
Для обновления индексного Array-поля, находящееся внутри массива объектов, через Go используйте метод Set().
db.Query("test").Where("nested", reindexer.EQ, 1).Set("nested[1].field1", 123).Update()
UPDATE ns SET nested[1].field1 = 123 WHERE nested = 1
curl --location --request PUT 'http://127.0.0.1:9088/api/v1/db/testdb/query' \
--header 'Content-Type: application/json' \
--data-raw '{
"namespace": "ns",
"filters": [
{
"Field": "nested",
"Cond": "EQ",
"Value": [
1
]
}
],
"update_fields": [
{
"name": "nested[1].field1",
"values": [
123
]
}
]
}'
Обновление индексного поля, находящегося внутри массива объектов, с заменой типа поля (массив->скаляр и наоборот):
Reindexer позволяет обновлять индексные поля, находящееся внутри массива объектов, и одновременно с этим менять их тип.
Такое обновление доступно только для смены типа поля со скалярного на массив и наоборот.
Пример ниже рассмотрен для неймспейса с именем ns, в котором есть индекс с параметрами: name="nested_field",json_paths=["nested.field1"] и is_array=true.
Исходная запись:
{
"id":1,
"nested":[{"field1": [1,2]},{"field1": 3 }] // Тип поля "field1" — массив
}
Запись после обновления и изменения типа индексного поля, находящегося внутри массива объектов, с массива на скалярный:
{
"id":1,
"nested":[{"field1": 123},{"field1": 3 }] // Тип поля "field1" — изменен на скалярный
}
Для обновления индексного Array-поля, находящееся внутри массива объектов, через Go используйте метод Set().
db.Query("test").Where("nested_field", reindexer.EQ, 1).Set("nested[0].field1", 123).Update()
UPDATE ns SET nested[0].field1 = 123 WHERE nested_field = 1
curl --location --request PUT 'http://127.0.0.1:9088/api/v1/db/testdb/query' \
--header 'Content-Type: application/json' \
--data-raw '{
"namespace": "ns",
"filters": [
{
"Field": "nested_field",
"Cond": "EQ",
"Value": [
1
]
}
],
"update_fields": [
{
"name": "nested[0].field1",
"values": [
123
]
}
]
}'
Изменение и добавление полей объектов
Reindexer позволяет обновлять и добавлять поля объектов. Объект может быть задан как struct, map или в виде байтового массива (то есть JSON-версии представления объекта).
Пример:
type ClientData struct {
Name string `reindex:"name" json:"name"`
Age int `reindex:"age" json:"age"`
Address int `reindex:"year" json:"year"`
Occupation string `reindex:"occupation" json:"occupation"`
TaxYear int `reindex:tax_year json:"tax_year"`
TaxConsultant string `reindex:tax_consultant json:"tax_consultant"`
}
type Client struct {
ID int `reindex:"id" json:"id"`
Data ClientData `reindex:"client_data" json:"client_data"`
...
}
clientData := updateClientData(clientId)
db.Query("clients").Where("id", reindexer.EQ, 100).SetObject("client_data", clientData).Update()
При передаче объекта в SetObject в виде map требуется использовать map с ключами типа string (например, map[string]interface{}).
UPDATE-запросы для удаления полей записей
В Reindexer используется следующий синтаксис UPDATE-запросов для удаления полей:
UPDATE nsName
DROP field1, field2, ..
WHERE condition;
С помощью таких запросов можно удалить только неиндексные поля или индексные
sparse-поля.
Примеры:
db.Query("items").Where("id", reindexer.EQ, 1).Drop("fieldToDrop1").Drop("fieldToDrop2").Update()
UPDATE items DROP fieldToDrop1, fieldToDrop2 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",
"filters": [
{
"Field": "id",
"Cond": "EQ",
"Value": [
1
]
}
],
"drop_fields": [
"fieldToDrop1",
"fieldToDrop2"
]
}'
Удаление элемента массива по индексу
Примеры команд для удаления элемента массива:
db.Query("items").Where("id", reindexer.EQ, 1).Drop("arrayField[2]").Update()
UPDATE items DROP arrayField[2] WHERE id = 11
curl --location --request PUT 'http://127.0.0.1:9088/api/v1/db/testdb/query' \
--header 'Content-Type: application/json' \
--data-raw '{
"namespace": "items",
"filters": [
{
"Field": "id",
"Cond": "EQ",
"Value": [
1
]
}
],
"drop_fields" : [
"arrayField[2]"
]
}'
Удаление элементов массива по значению
Для удаления элементов массива по значению используются функции:
array_remove(). Удаляет из массива все найденные вхождения элементов, переданных в качестве аргументов.array_remove_once(). Удаляет из массива только первые найденные вхождения элементов, переданных в качестве аргументов. Удаление происходит по числу вхождений: если какое-то значение задано несколько раз, то и из целевого массива будет удалено столько же его копий.
Функции могут принимать в качестве аргумента одно или несколько значений. В обоих случаях значения указываются в квадратных скобках.
Пример удаления всех найденных вхождений элементов, переданных в качестве аргументов, с помощью array_remove:
В Go
array_removeиспользуется через методSetExpression().
db.Query("items").Where("id", reindexer.EQ, 1).SetExpression("arrayField", "array_remove(arrayField, [5,6,7,8])").Update()
UPDATE items SET arrayField = array_remove(arrayField, [5,6,7,8]) WHERE id = 1
curl --location --request PUT 'http://127.0.0.1:9098/api/v1/db/mydb/query' \
--header 'Content-Type: application/json' \
--data '{
"namespace": "items",
"filters": [
{
"Field": "id",
"Cond": "EQ",
"Value": [
1
]
}
],
"update_fields": [
{
"name": "arrayField",
"type": "expression",
"is_array": false,
"values": [
"array_remove(arrayField, [5,6,7,8])"
]
}
]
}'
Пример удаления из массива только первых найденных вхождений элементов, переданных в качестве аргументов, помощью array_remove_once:
В Go
array_remove_onceиспользуется через методSetExpression().
db.Query("items").Where("id", reindexer.EQ, 1).SetExpression("arrayField", "array_remove_once(arrayField, [5,5,5,6])").Update()
UPDATE items SET arrayField = array_remove_once(arrayField, [5,5,5,6]) WHERE id = 1
curl --location --request PUT 'http://127.0.0.1:9098/api/v1/db/mydb/query' \
--header 'Content-Type: application/json' \
--data '{
"namespace": "items",
"filters": [
{
"Field": "id",
"Cond": "EQ",
"Value": [
1
]
}
],
"update_fields": [
{
"name": "arrayField",
"type": "expression",
"is_array": false,
"values": [
"array_remove_once(arrayField, [5,5,5,6])"
]
}
]
}'
Использование array_remove и array_remove_once можно комбинировать с добавлением элементов в начало или конец массива:
db.Query("items").Where("id", reindexer.EQ, 1).SetExpression("arrayField", "array_remove(arrayField, [5,6,7,8]) || [1,2,3]").Update()
UPDATE items SET arrayField = array_remove(arrayField, [5,6,7,8]) || [1,2,3] WHERE id = 1
curl --location --request PUT 'http://127.0.0.1:9098/api/v1/db/mydb/query' \
--header 'Content-Type: application/json' \
--data '{
"namespace": "items",
"filters": [
{
"Field": "id",
"Cond": "EQ",
"Value": [
1
]
}
],
"update_fields": [
{
"name": "arrayField",
"type": "expression",
"is_array": false,
"values": [
"array_remove(arrayField, [5,6,7,8]) || [1,2,3]"
]
}
]
}'
В качестве второго параметра в array_remove и array_remove_once может быть использован не только набор значений, но и имя поля, содержащего массив:
db.Query("items").Where("id", reindexer.EQ, 1).SetExpression("arrayField", "array_remove(arrayField, arrayField2)").Update()
UPDATE items SET arrayField = array_remove(arrayField, arrayField2) WHERE id = 1
curl --location --request PUT 'http://127.0.0.1:9098/api/v1/db/mydb/query' \
--header 'Content-Type: application/json' \
--data '{
"namespace": "items",
"filters": [
{
"Field": "id",
"Cond": "EQ",
"Value": [
1
]
}
],
"update_fields": [
{
"name": "arrayField",
"type": "expression",
"is_array": false,
"values": [
"array_remove(arrayField, arrayField2)"
]
}
]
}'
Указание набора значений или имени поля, содержащего массив, в качестве набора значений для удаления из другого можно комбинировать с добавлением элементов в начало или конец массива:
db.Query("items").Where("id", reindexer.EQ, 1).SetExpression("arrayField", "[3] || array_remove(arrayField, arrayField2) || arrayField3 || array_remove(arrayField, [8,1]) || [2,4]").Update()
UPDATE items SET arrayField = [3] || array_remove(arrayField, arrayField2) || arrayField3 || array_remove(arrayField, [8,1]) || [2,4] WHERE id = 1
curl --location --request PUT 'http://127.0.0.1:9098/api/v1/db/mydb/query' \
--header 'Content-Type: application/json' \
--data '{
"namespace": "items",
"filters": [
{
"Field": "id",
"Cond": "EQ",
"Value": [
1
]
}
],
"update_fields": [
{
"name": "arrayField",
"type": "expression",
"is_array": false,
"values": [
"[3] || array_remove(arrayField, arrayField2) || arrayField3 || array_remove(arrayField, [8,1]) || [2,4]"
]
}
]
}'
array_remove и array_remove_once можно использовать для инициализации массива отфильтрованными значениями из другого поля:
db.Query("items").Where("id", reindexer.EQ, 1).SetExpression("arrayField", "array_remove(arrayField2, arrayField3)").Update()
db.Query("items").Where("id", reindexer.EQ, 1).SetExpression("arrayField", "array_remove([1,2,3], arrayField2)").Update()
UPDATE items SET arrayField = array_remove(arrayField2, arrayField3) WHERE id = 1
UPDATE items SET arrayField = array_remove([1,2,3], arrayField2) WHERE id = 1
curl --location --request PUT 'http://127.0.0.1:9098/api/v1/db/mydb/query' \
--header 'Content-Type: application/json' \
--data '{
"namespace": "items",
"filters": [
{
"Field": "id",
"Cond": "EQ",
"Value": [
1
]
}
],
"update_fields": [
{
"name": "arrayField",
"type": "expression",
"is_array": false,
"values": [
"array_remove(arrayField2, arrayField3)"
]
}
]
}'
curl --location --request PUT 'http://127.0.0.1:9098/api/v1/db/mydb/query' \
--header 'Content-Type: application/json' \
--data '{
"namespace": "items",
"filters": [
{
"Field": "id",
"Cond": "EQ",
"Value": [
1
]
}
],
"update_fields": [
{
"name": "arrayField",
"type": "expression",
"is_array": false,
"values": [
"array_remove([1,2,3], arrayField2)"
]
}
]
}'
DELETE-запросы
DELETE-запросы в Reindexer используются для удаления одной или нескольких записей из неймспейса. Пример:
db.Query("items").Where("id", reindexer.EQ, 11).Delete()
DELETE FROM items WHERE id = 11
curl --location --request DELETE 'http://127.0.0.1:9088/api/v1/db/testdb/query' \
--header 'Content-Type: application/json' \
--data-raw '{
"namespace": "items",
"filters": [
{
"Field": "id",
"Cond": "EQ",
"Value": [
1
]
}
]
}'