Запросы для обновления и удаления данных
Запросы для обновления (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
]
}
]
}'