≫ Обновление документов
You can modify existing data in an RT or PQ table by either updating or replacing it.
UPDATE заменяет построчно значения атрибутов существующих документов новыми значениями. Полнотекстовые поля и колоннарные атрибуты нельзя обновлять. Если вам нужно изменить содержимое полнотекстового поля или колоннарных атрибутов, используйте REPLACE.
REPLACE работает аналогично INSERT, за исключением того, что если у старого документа тот же ID, что и у нового, старый документ помечается как удалённый перед вставкой нового документа. Обратите внимание, что старый документ физически не удаляется из таблицы. Удаление может произойти только при слиянии чанков в таблице, например, в результате OPTIMIZE.
Both UPDATE and a partial REPLACE can change the value of a field, but they operate differently:
UPDATEможет изменять только поля, которые не являются колоннарными или полнотекстовыми. Этот процесс выполняется на месте, что обычно быстрее, чемREPLACE.- Частичный
REPLACEможет изменить любое поле в документе, но требует, чтобы все поля в таблице были установлены как "stored" (хотя это настройка по умолчанию). Это не требуется при использованииUPDATE.
REPLACE работает аналогично INSERT, но перед вставкой нового документа помечает предыдущий документ с тем же ID как удалённый.
Если вам нужны обновления на месте, пожалуйста, смотрите этот раздел.
Синтаксис SQL оператора REPLACE следующий:
Для замены всего документа:
REPLACE INTO table [(column1, column2, ...)]
VALUES (value1, value2, ...)
[, (...)]
Столбцы, явно не включённые в SQL-запрос, устанавливаются в значения по умолчанию, такие как 0 или пустая строка, в зависимости от их типа данных.
Для замены только выбранных полей:
REPLACE INTO table
SET field1=value1[, ..., fieldN=valueN]
WHERE id = <id>
Обратите внимание, что в этом режиме фильтровать можно только по id.
ПРИМЕЧАНИЕ: Частичная замена требует Manticore Buddy. Если не работает, убедитесь, что Buddy установлен.
Подробнее о UPDATE и частичной замене REPLACE читайте здесь.
Смотрите примеры для более подробной информации.
-
/replace:POST /replace { "table": "<table name>", "id": <document id>, "doc": { "<field1>": <value1>, ... "<fieldN>": <valueN> } }/index— это псевдоним эндпоинта и работает так же. -
Эндпоинт в стиле Elasticsearch
<table>/_doc/<id>:PUT/POST /<table name>/_doc/<id> { "<field1>": <value1>, ... "<fieldN>": <valueN> }ПРИМЕЧАНИЕ: Замена в стиле Elasticsearch требует Manticore Buddy. Если не работает, убедитесь, что Buddy установлен.
-
Частичная замена:
POST /<{table | cluster:table}>/_update/<id> { "<field1>": <value1>, ... "<fieldN>": <valueN> }<table name>может быть просто именем таблицы или в форматеcluster:table. Это позволяет выполнять обновления по конкретному кластеру при необходимости.ПРИМЕЧАНИЕ: Частичная замена требует Manticore Buddy. Если не работает, убедитесь, что Buddy установлен.
Смотрите примеры для более подробной информации.
- SQL
- REPLACE SET
- JSON
- Elasticsearch-like
- Elasticsearch-like partial
- Elasticsearch-like partial in cluster
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
- TypeScript
- Go
REPLACE INTO products VALUES(1, "document one", 10);REPLACE INTO products SET description='HUAWEI Matebook 15', price=10 WHERE id = 55;POST /replace
-H "Content-Type: application/x-ndjson" -d '
{
"table":"products",
"id":1,
"doc":
{
"title":"product one",
"price":10
}
}
'ПРИМЕЧАНИЕ: Замена в стиле Elasticsearch требует Manticore Buddy. Если не работает, убедитесь, что Buddy установлен.
PUT /products/_doc/2
{
"title": "product two",
"price": 20
}
POST /products/_doc/3
{
"title": "product three",
"price": 10
}ПРИМЕЧАНИЕ: Частичная замена требует Manticore Buddy. Если не работает, убедитесь, что Buddy установлен.
POST /products/_update/55
{
"doc": {
"description": "HUAWEI Matebook 15",
"price": 10
}
}POST /cluster_name:products/_update/55
{
"doc": {
"description": "HUAWEI Matebook 15",
"price": 10
}
}$index->replaceDocument([
'title' => 'document one',
'price' => 10
],1);indexApi.replace({"table" : "products", "id" : 1, "doc" : {"title" : "document one","price":10}})await indexApi.replace({"table" : "products", "id" : 1, "doc" : {"title" : "document one","price":10}})res = await indexApi.replace({"table" : "products", "id" : 1, "doc" : {"title" : "document one","price":10}});docRequest = new InsertDocumentRequest();
HashMap<String,Object> doc = new HashMap<String,Object>(){{
put("title","document one");
put("price",10);
}};
docRequest.index("products").id(1L).setDoc(doc);
sqlresult = indexApi.replace(docRequest);Dictionary<string, Object> doc = new Dictionary<string, Object>();
doc.Add("title", "document one");
doc.Add("price", 10);
InsertDocumentRequest docRequest = new InsertDocumentRequest(index: "products", id: 1, doc: doc);
var sqlresult = indexApi.replace(docRequest);let mut doc = HashMap::new();
doc.insert("title".to_string(), serde_json::json!("document one"));
doc.insert("price".to_string(), serde_json::json!(10));
let insert_req = InsertDocumentRequest::new("products".to_string(), serde_json::json!(doc));
let insert_res = index_api.replace(insert_req).await;res = await indexApi.replace({
index: 'test',
id: 1,
doc: { content: 'Text 11', name: 'Doc 11', cat: 3 },
});replaceDoc := map[string]interface{} {"content": "Text 11", "name": "Doc 11", "cat": 3}
replaceRequest := manticoreclient.NewInsertDocumentRequest("test", replaceDoc)
replaceRequest.SetId(1)
res, _, _ := apiClient.IndexAPI.Replace(context.Background()).InsertDocumentRequest(*replaceRequest).Execute()Query OK, 1 row affected (0.00 sec)Query OK, 1 row affected (0.00 sec){
"table":"products",
"_id":1,
"created":false,
"result":"updated",
"status":200
}{
"_id":2,
"table":"products",
"_primary_term":1,
"_seq_no":0,
"_shards":{
"failed":0,
"successful":1,
"total":1
},
"_type":"_doc",
"_version":1,
"result":"updated"
}
{
"_id":3,
"table":"products",
"_primary_term":1,
"_seq_no":0,
"_shards":{
"failed":0,
"successful":1,
"total":1
},
"_type":"_doc",
"_version":1,
"result":"updated"
}{
"table":"products",
"updated":1
}{
"table":"products",
"updated":1
}Array(
[_index] => products
[_id] => 1
[created] => false
[result] => updated
[status] => 200
){'created': False,
'found': None,
'id': 1,
'table': 'products',
'result': 'updated'}{'created': False,
'found': None,
'id': 1,
'table': 'products',
'result': 'updated'}{"table":"products","_id":1,"result":"updated"}class SuccessResponse {
index: products
id: 1
created: false
result: updated
found: null
}class SuccessResponse {
index: products
id: 1
created: false
result: updated
found: null
}class SuccessResponse {
index: products
id: 1
created: false
result: updated
found: null
}{
"table":"test",
"_id":1,
"created":false
"result":"updated"
"status":200
}{
"table":"test",
"_id":1,
"created":false
"result":"updated"
"status":200
}REPLACE доступен для real-time и percolate таблиц. Нельзя заменять данные в plain таблице.
При выполнении REPLACE предыдущий документ не удаляется, а помечается как удалённый, поэтому размер таблицы растёт до тех пор, пока не произойдёт слияние чанков. Чтобы принудительно выполнить слияние чанков, используйте оператор OPTIMIZE.
Вы можете заменить несколько документов одновременно. Подробнее смотрите в разделе bulk adding documents.
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
- TypeScript
- Go
REPLACE INTO products(id,title,tag) VALUES (1, 'doc one', 10), (2,' doc two', 20);POST /bulk
-H "Content-Type: application/x-ndjson" -d '
{ "replace" : { "table" : "products", "id":1, "doc": { "title": "doc one", "tag" : 10 } } }
{ "replace" : { "table" : "products", "id":2, "doc": { "title": "doc two", "tag" : 20 } } }
'$index->replaceDocuments([
[
'id' => 1,
'title' => 'document one',
'tag' => 10
],
[
'id' => 2,
'title' => 'document one',
'tag' => 20
]
);indexApi = manticoresearch.IndexApi(client)
docs = [ \
{"replace": {"table" : "products", "id" : 1, "doc" : {"title" : "document one"}}}, \
{"replace": {"table" : "products", "id" : 2, "doc" : {"title" : "document two"}}} ]
api_resp = indexApi.bulk('\n'.join(map(json.dumps,docs)))indexApi = manticoresearch.IndexApi(client)
docs = [ \
{"replace": {"table" : "products", "id" : 1, "doc" : {"title" : "document one"}}}, \
{"replace": {"table" : "products", "id" : 2, "doc" : {"title" : "document two"}}} ]
api_resp = await indexApi.bulk('\n'.join(map(json.dumps,docs)))docs = [
{"replace": {"table" : "products", "id" : 1, "doc" : {"title" : "document one"}}},
{"replace": {"table" : "products", "id" : 2, "doc" : {"title" : "document two"}}} ];
res = await indexApi.bulk(docs.map(e=>JSON.stringify(e)).join('\n'));body = "{\"replace\": {\"index\" : \"products\", \"id\" : 1, \"doc\" : {\"title\" : \"document one\"}}}" +"\n"+
"{\"replace\": {\"index\" : \"products\", \"id\" : 2, \"doc\" : {\"title\" : \"document two\"}}}"+"\n" ;
indexApi.bulk(body);string body = "{\"replace\": {\"index\" : \"products\", \"id\" : 1, \"doc\" : {\"title\" : \"document one\"}}}" +"\n"+
"{\"replace\": {\"index\" : \"products\", \"id\" : 2, \"doc\" : {\"title\" : \"document two\"}}}"+"\n" ;
indexApi.Bulk(body);string body = r#"{"replace": {"index" : "products", "id" : 1, "doc" : {"title" : "document one"}}}
{"replace": {"index" : "products", "id" : 2, "doc" : {"title" : "document two"}}}
"#;
index_api.bulk(body).await;replaceDocs = [
{
replace: {
index: 'test',
id: 1,
doc: { content: 'Text 11', cat: 1, name: 'Doc 11' },
},
},
{
replace: {
index: 'test',
id: 2,
doc: { content: 'Text 22', cat: 9, name: 'Doc 22' },
},
},
];
res = await indexApi.bulk(
replaceDocs.map((e) => JSON.stringify(e)).join("\n")
);body := "{\"replace\": {\"index\": \"test\", \"id\": 1, \"doc\": {\"content\": \"Text 11\", \"name\": \"Doc 11\", \"cat\": 1 }}}" + "\n" +
"{\"replace\": {\"index\": \"test\", \"id\": 2, \"doc\": {\"content\": \"Text 22\", \"name\": \"Doc 22\", \"cat\": 9 }}}" +"\n";
res, _, _ := apiClient.IndexAPI.Bulk(context.Background()).Body(body).Execute()Query OK, 2 rows affected (0.00 sec){
"items":
[
{
"replace":
{
"table":"products",
"_id":1,
"created":false,
"result":"updated",
"status":200
}
},
{
"replace":
{
"table":"products",
"_id":2,
"created":false,
"result":"updated",
"status":200
}
}
],
"errors":false
}Array(
[items] =>
Array(
Array(
[_index] => products
[_id] => 2
[created] => false
[result] => updated
[status] => 200
)
Array(
[_index] => products
[_id] => 2
[created] => false
[result] => updated
[status] => 200
)
)
[errors => false
){'error': None,
'items': [{u'replace': {u'_id': 1,
u'table': u'products',
u'created': False,
u'result': u'updated',
u'status': 200}},
{u'replace': {u'_id': 2,
u'table': u'products',
u'created': False,
u'result': u'updated',
u'status': 200}}]}{'error': None,
'items': [{u'replace': {u'_id': 1,
u'table': u'products',
u'created': False,
u'result': u'updated',
u'status': 200}},
{u'replace': {u'_id': 2,
u'table': u'products',
u'created': False,
u'result': u'updated',
u'status': 200}}]}{"items":[{"replace":{"table":"products","_id":1,"created":false,"result":"updated","status":200}},{"replace":{"table":"products","_id":2,"created":false,"result":"updated","status":200}}],"errors":false}class BulkResponse {
items: [{replace={_index=products, _id=1, created=false, result=updated, status=200}}, {replace={_index=products, _id=2, created=false, result=updated, status=200}}]
error: null
additionalProperties: {errors=false}
}class BulkResponse {
items: [{replace={_index=products, _id=1, created=false, result=updated, status=200}}, {replace={_index=products, _id=2, created=false, result=updated, status=200}}]
error: null
additionalProperties: {errors=false}
}class BulkResponse {
items: [{replace={_index=products, _id=1, created=false, result=updated, status=200}}, {replace={_index=products, _id=2, created=false, result=updated, status=200}}]
error: null
additionalProperties: {errors=false}
}{
"items":
[
{
"replace":
{
"table":"test",
"_id":1,
"created":false,
"result":"updated",
"status":200
}
},
{
"replace":
{
"table":"test",
"_id":2,
"created":false,
"result":"updated",
"status":200
}
}
],
"errors":false
}{
"items":
[
{
"replace":
{
"table":"test",
"_id":1,
"created":false,
"result":"updated",
"status":200
}
},
{
"replace":
{
"table":"test",
"_id":2,
"created":false,
"result":"updated",
"status":200
}
}
],
"errors":false
}Команда UPDATE изменяет построчно значения атрибутов существующих документов в указанной таблице на новые значения. Обратите внимание, что нельзя обновлять содержимое поля полнотекстового поиска или колонного атрибута. Если возникает такая необходимость, используйте REPLACE.
Обновление атрибутов поддерживается для RT, PQ и обычных таблиц. Все типы атрибутов могут быть обновлены, если они хранятся в построчном хранилище.
Обратите внимание, что идентификатор документа обновить нельзя.
Важно понимать, что обновление атрибута отключает его вторичный индекс. Если критично поддерживать непрерывность вторичного индекса, рассмотрите возможность полного или частичного замещения документа.
Подробнее о UPDATE и частичном REPLACE читайте здесь.
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
- TypeScript
- Go
UPDATE products SET enabled=0 WHERE id=10;POST /update
{
"table":"products",
"id":10,
"doc":
{
"enabled":0
}
}$index->updateDocument([
'enabled'=>0
],10);indexApi = api = manticoresearch.IndexApi(client)
indexApi.update({"table" : "products", "id" : 1, "doc" : {"price":10}})indexApi = api = manticoresearch.IndexApi(client)
await indexApi.update({"table" : "products", "id" : 1, "doc" : {"price":10}})res = await indexApi.update({"table" : "products", "id" : 1, "doc" : {"price":10}});UpdateDocumentRequest updateRequest = new UpdateDocumentRequest();
doc = new HashMap<String,Object >(){{
put("price",10);
}};
updateRequest.index("products").id(1L).setDoc(doc);
indexApi.update(updateRequest);Dictionary<string, Object> doc = new Dictionary<string, Object>();
doc.Add("price", 10);
UpdateDocumentRequest updateRequest = new UpdateDocumentRequest(index: "products", id: 1, doc: doc);
indexApi.Update(updateRequest);let mut doc = HashMap::new();
doc.insert("price".to_string(), serde_json::json!(10));
let update_req = UpdateDocumentRequest {
table: serde_json::json!("products"),
doc: serde_json::json!(doc),
id: serde_json::json!(1),
..Default::default(),
};
let update_res = index_api.update(update_req).await;res = await indexApi.update({ index: "test", id: 1, doc: { cat: 10 } });updateDoc = map[string]interface{} {"cat":10}
updateRequest = openapiclient.NewUpdateDocumentRequest("test", updateDoc)
updateRequest.SetId(1)
res, _, _ = apiClient.IndexAPI.Update(context.Background()).UpdateDocumentRequest(*updateRequest).Execute()Query OK, 1 row affected (0.00 sec){
"table":"products",
"updated":1
}Array(
[_index] => products
[_id] => 10
[result] => updated
){'id': 1, 'table': 'products', 'result': 'updated', 'updated': None}{'id': 1, 'table': 'products', 'result': 'updated', 'updated': None}{"table":"products","_id":1,"result":"updated"}class UpdateResponse {
index: products
updated: null
id: 1
result: updated
}class UpdateResponse {
index: products
updated: null
id: 1
result: updated
}class UpdateResponse {
index: products
updated: null
id: 1
result: updated
}{
"table":"test",
"_id":1,
"result":"updated"
}{
"table":"test",
"_id":1,
"result":"updated"
}В одном операторе можно обновить несколько атрибутов. Пример:
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
- TypeScript
- Go
UPDATE products
SET price=100000000000,
coeff=3465.23,
tags1=(3,6,4),
tags2=()
WHERE MATCH('phone') AND enabled=1;POST /update
{
"table":"products",
"doc":
{
"price":100000000000,
"coeff":3465.23,
"tags1":[3,6,4],
"tags2":[]
},
"query":
{
"match": { "*": "phone" },
"equals": { "enabled": 1 }
}
}$query= new BoolQuery();
$query->must(new Match('phone','*'));
$query->must(new Equals('enabled',1));
$index->updateDocuments([
'price' => 100000000000,
'coeff' => 3465.23,
'tags1' => [3,6,4],
'tags2' => []
],
$query
);indexApi = api = manticoresearch.IndexApi(client)
indexApi.update({"table" : "products", "id" : 1, "doc" : {
"price": 100000000000,
"coeff": 3465.23,
"tags1": [3,6,4],
"tags2": []}})indexApi = api = manticoresearch.IndexApi(client)
await indexApi.update({"table" : "products", "id" : 1, "doc" : {
"price": 100000000000,
"coeff": 3465.23,
"tags1": [3,6,4],
"tags2": []}})res = await indexApi.update({"table" : "products", "id" : 1, "doc" : {
"price": 100000000000,
"coeff": 3465.23,
"tags1": [3,6,4],
"tags2": []}});UpdateDocumentRequest updateRequest = new UpdateDocumentRequest();
doc = new HashMap<String,Object >(){{
put("price",10);
put("coeff",3465.23);
put("tags1",new int[]{3,6,4});
put("tags2",new int[]{});
}};
updateRequest.index("products").id(1L).setDoc(doc);
indexApi.update(updateRequest);Dictionary<string, Object> doc = new Dictionary<string, Object>();
doc.Add("price", 10);
doc.Add("coeff", 3465.23);
doc.Add("tags1", new List<int> {3,6,4});
doc.Add("tags2", new List<int> {});
UpdateDocumentRequest updateRequest = new UpdateDocumentRequest(index: "products", id: 1, doc: doc);
indexApi.Update(updateRequest);let mut doc = HashMap::new();
doc.insert("price".to_string(), serde_json::json!(10));
doc.insert("coeff".to_string(), serde_json::json!(3465.23));
doc.insert("tags1".to_string(), serde_json::json!([3,6,4]));
doc.insert("tags2".to_string(), serde_json::json!([]));
let update_req = UpdateDocumentRequest {
table: serde_json::json!("products"),
doc: serde_json::json!(doc),
id: serde_json::json!(1),
..Default::default(),
};
let update_res = index_api.update(update_req).await;res = await indexApi.update({ index: "test", id: 1, doc: { name: "Doc 21", cat: "10" } });updateDoc = map[string]interface{} {"name":"Doc 21", "cat":10}
updateRequest = manticoreclient.NewUpdateDocumentRequest("test", updateDoc)
updateRequest.SetId(1)
res, _, _ = apiClient.IndexAPI.Update(context.Background()).UpdateDocumentRequest(*updateRequest).Execute()Query OK, 148 rows affected (0.0 sec){
"table":"products",
"updated":148
}Array(
[_index] => products
[updated] => 148
){'id': 1, 'table': 'products', 'result': 'updated', 'updated': None}{'id': 1, 'table': 'products', 'result': 'updated', 'updated': None}{"table":"products","_id":1,"result":"updated"}class UpdateResponse {
index: products
updated: null
id: 1
result: updated
}class UpdateResponse {
index: products
updated: null
id: 1
result: updated
}class UpdateResponse {
index: products
updated: null
id: 1
result: updated
}{
"table":"test",
"_id":1,
"result":"updated"
}{
"table":"test",
"_id":1,
"result":"updated"
}При присвоении выходящих за диапазон значений 32-битным атрибутам они будут усечены до младших 32 бит без предупреждения. Например, если попытаться обновить 32-битное беззнаковое целое значением 4294967297, фактически будет сохранено значение 1, так как младшие 32 бита числа 4294967297 (0x100000001 в шестнадцатеричном виде) равны 1 (0x00000001 в шестнадцатеричном виде).
UPDATE можно использовать для частичного обновления JSON с числовыми типами данных или массивами числовых типов. Главное — не обновлять целочисленное значение числом с плавающей точкой, так как оно будет округлено.
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
- TypeScript
- Go
insert into products (id, title, meta) values (1,'title','{"tags":[1,2,3]}');
update products set meta.tags[0]=100 where id=1;POST /insert
{
"table":"products",
"id":100,
"doc":
{
"title":"title",
"meta": {
"tags":[1,2,3]
}
}
}
POST /update
{
"table":"products",
"id":100,
"doc":
{
"meta.tags[0]":100
}
}$index->insertDocument([
'title' => 'title',
'meta' => ['tags' => [1,2,3]]
],1);
$index->updateDocument([
'meta.tags[0]' => 100
],1);indexApi = api = manticoresearch.IndexApi(client)
indexApi.update({"table" : "products", "id" : 1, "doc" : {
"meta.tags[0]": 100}})indexApi = api = manticoresearch.IndexApi(client)
await indexApi.update({"table" : "products", "id" : 1, "doc" : {
"meta.tags[0]": 100}})res = await indexApi.update({"table" : "products", "id" : 1, "doc" : {
"meta.tags[0]": 100}});UpdateDocumentRequest updateRequest = new UpdateDocumentRequest();
doc = new HashMap<String,Object >(){{
put("meta.tags[0]",100);
}};
updateRequest.index("products").id(1L).setDoc(doc);
indexApi.update(updateRequest);Dictionary<string, Object> doc = new Dictionary<string, Object>();
doc.Add("meta.tags[0]", 100);
UpdateDocumentRequest updateRequest = new UpdateDocumentRequest(index: "products", id: 1, doc: doc);
indexApi.Update(updateRequest);let mut doc = HashMap::new();
doc.insert("meta.tags[0]".to_string(), serde_json::json!(100));
let update_req = UpdateDocumentRequest {
table: serde_json::json!("products"),
doc: serde_json::json!(doc),
id: serde_json::json!(1),
..Default::default(),
};
let update_res = index_api.update(update_req).await;res = await indexApi.update({"table" : "test", "id" : 1, "doc" : { "meta.tags[0]": 100} });updateDoc = map[string]interface{} {"meta.tags[0]":100}
updateRequest = manticoreclient.NewUpdateDocumentRequest("test", updateDoc)
updateRequest.SetId(1)
res, _, _ = apiClient.IndexAPI.Update(context.Background()).UpdateDocumentRequest(*updateRequest).Execute()Query OK, 1 row affected (0.00 sec)
Query OK, 1 row affected (0.00 sec){
"table":"products",
"_id":100,
"created":true,
"result":"created",
"status":201
}
{
"table":"products",
"updated":1
}Array(
[_index] => products
[_id] => 1
[created] => true
[result] => created
)
Array(
[_index] => products
[updated] => 1
){'id': 1, 'table': 'products', 'result': 'updated', 'updated': None}{'id': 1, 'table': 'products', 'result': 'updated', 'updated': None}{"table":"products","_id":1,"result":"updated"}class UpdateResponse {
index: products
updated: null
id: 1
result: updated
}class UpdateResponse {
index: products
updated: null
id: 1
result: updated
}class UpdateResponse {
index: products
updated: null
id: 1
result: updated
}{"table":"test","_id":1,"result":"updated"}{
"table":"test",
"_id":1,
"result":"updated"
}Обновление других типов данных или изменение типа свойства в JSON-атрибуте требует полного обновления JSON.
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
- TypeScript
- Go
insert into products values (1,'title','{"tags":[1,2,3]}');
update products set data='{"tags":["one","two","three"]}' where id=1;POST /insert
{
"table":"products",
"id":1,
"doc":
{
"title":"title",
"data":"{\"tags\":[1,2,3]}"
}
}
POST /update
{
"table":"products",
"id":1,
"doc":
{
"data":"{\"tags\":[\"one\",\"two\",\"three\"]}"
}
}$index->insertDocument([
'title'=> 'title',
'data' => [
'tags' => [1,2,3]
]
],1);
$index->updateDocument([
'data' => [
'one', 'two', 'three'
]
],1);indexApi.insert({"table" : "products", "id" : 100, "doc" : {"title" : "title", "meta" : {"tags":[1,2,3]}}})
indexApi.update({"table" : "products", "id" : 100, "doc" : {"meta" : {"tags":['one','two','three']}}})await indexApi.insert({"table" : "products", "id" : 100, "doc" : {"title" : "title", "meta" : {"tags":[1,2,3]}}})
await indexApi.update({"table" : "products", "id" : 100, "doc" : {"meta" : {"tags":['one','two','three']}}})res = await indexApi.insert({"table" : "products", "id" : 100, "doc" : {"title" : "title", "meta" : {"tags":[1,2,3]}}});
res = await indexApi.update({"table" : "products", "id" : 100, "doc" : {"meta" : {"tags":['one','two','three']}}});InsertDocumentRequest newdoc = new InsertDocumentRequest();
doc = new HashMap<String,Object>(){{
put("title","title");
put("meta",
new HashMap<String,Object>(){{
put("tags",new int[]{1,2,3});
}});
}};
newdoc.index("products").id(100L).setDoc(doc);
indexApi.insert(newdoc);
updatedoc = new UpdateDocumentRequest();
doc = new HashMap<String,Object >(){{
put("meta",
new HashMap<String,Object>(){{
put("tags",new String[]{"one","two","three"});
}});
}};
updatedoc.index("products").id(100L).setDoc(doc);
indexApi.update(updatedoc);Dictionary<string, Object> meta = new Dictionary<string, Object>();
meta.Add("tags", new List<int> {1,2,3});
Dictionary<string, Object> doc = new Dictionary<string, Object>();
doc.Add("title", "title");
doc.Add("meta", meta);
InsertDocumentRequest newdoc = new InsertDocumentRequest(index: "products", id: 100, doc: doc);
indexApi.Insert(newdoc);
meta = new Dictionary<string, Object>();
meta.Add("tags", new List<string> {"one","two","three"});
doc = new Dictionary<string, Object>();
doc.Add("meta", meta);
UpdateDocumentRequest updatedoc = new UpdateDocumentRequest(index: "products", id: 100, doc: doc);
indexApi.Update(updatedoc);let mut meta = HashMap::new();
meta.insert("tags".to_string(), serde_json::json!([1,2,3]));
let mut doc = HashMap::new();
doc.insert("title".to_string(), serde_json::json!("title"));
doc.insert("meta".to_string(), serde_json::json!(meta));
let insert_req = InsertDocumentRequest {
table: serde_json::json!("products"),
doc: serde_json::json!(doc),
id: serde_json::json!(100),
..Default::default(),
};
let insert_res = index_api.insert(insert_req).await;
meta = HashMap::new();
meta.insert("tags".to_string(), serde_json::json!(["one","two","three"]));
doc = HashMap::new();
doc.insert("meta".to_string(), serde_json::json!(meta));
let update_req = UpdateDocumentRequest {
table: serde_json::json!("products"),
doc: serde_json::json!(doc),
id: serde_json::json!(100),
..Default::default(),
};
let update_res = index_api.update(update_req).await;res = await indexApi.insert({
index: 'test',
id: 1,
doc: { content: 'Text 1', name: 'Doc 1', meta: { tags:[1,2,3] } }
})
res = await indexApi.update({ index: 'test', id: 1, doc: { meta: { tags:['one','two','three'] } } });metaField := map[string]interface{} {"tags": []int{1, 2, 3}}
insertDoc := map[string]interface{} {"name": "Doc 1", "meta": metaField}}
insertRequest := manticoreclient.NewInsertDocumentRequest("test", insertDoc)
insertRequest.SetId(1)
res, _, _ := apiClient.IndexAPI.Insert(context.Background()).InsertDocumentRequest(*insertRequest).Execute();
metaField = map[string]interface{} {"tags": []string{"one", "two", "three"}}
updateDoc := map[string]interface{} {"meta": metaField}
updateRequest := manticoreclient.NewUpdateDocumentRequest("test", updateDoc)
res, _, _ = apiClient.IndexAPI.Update(context.Background()).UpdateDocumentRequest(*updateRequest).Execute()Query OK, 1 row affected (0.00 sec)
Query OK, 1 row affected (0.00 sec){
"table":"products",
"updated":1
}Array(
[_index] => products
[_id] => 1
[created] => true
[result] => created
)
Array(
[_index] => products
[updated] => 1
){'created': True,
'found': None,
'id': 100,
'table': 'products',
'result': 'created'}
{'id': 100, 'table': 'products', 'result': 'updated', 'updated': None}{'created': True,
'found': None,
'id': 100,
'table': 'products',
'result': 'created'}
{'id': 100, 'table': 'products', 'result': 'updated', 'updated': None}{"table":"products","_id":100,"created":true,"result":"created"}
{"table":"products","_id":100,"result":"updated"}class SuccessResponse {
index: products
id: 100
created: true
result: created
found: null
}
class UpdateResponse {
index: products
updated: null
id: 100
result: updated
}class SuccessResponse {
index: products
id: 100
created: true
result: created
found: null
}
class UpdateResponse {
index: products
updated: null
id: 100
result: updated
}class SuccessResponse {
index: products
id: 100
created: true
result: created
found: null
}
class UpdateResponse {
index: products
updated: null
id: 100
result: updated
}{
"table":"test",
"_id":1,
"created":true,
"result":"created"
}
{
"table":"test",
"_id":1,
"result":"updated"
}{
"table":"test",
"_id":1,
"created":true,
"result":"created"
}
{
"table":"test",
"_id":1,
"result":"updated"
}When using replication, the table name should be prepended with cluster_name: (in SQL) so that updates will be propagated to all nodes in the cluster. For queries via HTTP, you should set a cluster property. See setting up replication for more information.
{
"cluster":"nodes4",
"table":"test",
"id":1,
"doc":
{
"gid" : 100,
"price" : 1000
}
}
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
- TypeScript
- Go
update weekly:posts set enabled=0 where id=1;POST /update
{
"cluster":"weekly",
"table":"products",
"id":1,
"doc":
{
"enabled":0
}
}$index->setName('products')->setCluster('weekly');
$index->updateDocument(['enabled'=>0],1);indexApi.update({"cluster":"weekly", "table" : "products", "id" : 1, "doc" : {"enabled" : 0}})await indexApi.update({"cluster":"weekly", "table" : "products", "id" : 1, "doc" : {"enabled" : 0}})res = wait indexApi.update({"cluster":"weekly", "table" : "products", "id" : 1, "doc" : {"enabled" : 0}});updatedoc = new UpdateDocumentRequest();
doc = new HashMap<String,Object >(){{
put("enabled",0);
}};
updatedoc.index("products").cluster("weekly").id(1L).setDoc(doc);
indexApi.update(updatedoc);Dictionary<string, Object> doc = new Dictionary<string, Object>();
doc.Add("enabled", 0);
UpdateDocumentRequest updatedoc = new UpdateDocumentRequest(index: "products", cluster: "weekly", id: 1, doc: doc);
indexApi.Update(updatedoc);let mut doc = HashMap::new();
doc.insert("enabled".to_string(), serde_json::json!(0));
let update_req = UpdateDocumentRequest {
table: serde_json::json!("products"),
cluster: serde_json::json!("weekly"),
doc: serde_json::json!(doc),
id: serde_json::json!(1),
};
let update_res = index_api.update(update_req).await;res = wait indexApi.update( {cluster: 'test_cluster', index : 'test', id : 1, doc : {name : 'Doc 11'}} );updateDoc = map[string]interface{} {"name":"Doc 11"}
updateRequest = manticoreclient.NewUpdateDocumentRequest("test", updateDoc)
updateRequest.SetCluster("test_cluster")
updateRequest.SetId(1)
res, _, _ = apiClient.IndexAPI.Update(context.Background()).UpdateDocumentRequest(*updateRequest).Execute()Here is the syntax for the SQL UPDATE statement:
UPDATE table SET col1 = newval1 [, ...] WHERE where_condition [OPTION opt_name = opt_value [, ...]] [FORCE|IGNORE INDEX(id)]
where_condition has the same syntax as in the SELECT statement.
Multi-value attribute value sets must be specified as comma-separated lists in parentheses. To remove all values from a multi-value attribute, just assign () to it.
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
- TypeScript
- Go
UPDATE products SET tags1=(3,6,4) WHERE id=1;
UPDATE products SET tags1=() WHERE id=1;POST /update
{
"table":"products",
"_id":1,
"doc":
{
"tags1": []
}
}$index->updateDocument(['tags1'=>[]],1);indexApi.update({"table" : "products", "id" : 1, "doc" : {"tags1": []}})await indexApi.update({"table" : "products", "id" : 1, "doc" : {"tags1": []}})indexApi.update({"table" : "products", "id" : 1, "doc" : {"tags1": []}})updatedoc = new UpdateDocumentRequest();
doc = new HashMap<String,Object >(){{
put("tags1",new int[]{});
}};
updatedoc.index("products").id(1L).setDoc(doc);
indexApi.update(updatedoc);Dictionary<string, Object> doc = new Dictionary<string, Object>();
doc.Add("tags1", new List<int> {});
UpdateDocumentRequest updatedoc = new UpdateDocumentRequest(index: "products", id: 1, doc: doc);
indexApi.Update(updatedoc);let mut doc = HashMap::new();
doc.insert("tags1".to_string(), serde_json::json!([]));
let update_req = UpdateDocumentRequest {
table: serde_json::json!("products"),
doc: serde_json::json!(doc),
id: serde_json::json!(1),
..Default::default(),
};
let update_res = index_api.update(update_req).await;res = await indexApi.update({ index: 'test', id: 1, doc: { cat: 10 } });updateDoc = map[string]interface{} {"cat":10}
updateRequest = manticoreclient.NewUpdateDocumentRequest("test", updateDoc)
updateRequest.SetId(1)
res, _, _ = apiClient.IndexAPI.Update(context.Background()).UpdateDocumentRequest(*updateRequest).Execute()Query OK, 1 row affected (0.00 sec)
Query OK, 1 row affected (0.00 sec){
"table":"products",
"updated":1
}Array(
[_index] => products
[updated] => 1
){'id': 1, 'table': 'products', 'result': 'updated', 'updated': None}{'id': 1, 'table': 'products', 'result': 'updated', 'updated': None}{"table":"products","_id":1,"result":"updated"}class UpdateResponse {
index: products
updated: null
id: 1
result: updated
}class UpdateResponse {
index: products
updated: null
id: 1
result: updated
}class UpdateResponse {
index: products
updated: null
id: 1
result: updated
}{
"table":"test",
"_id":1,
"result":"updated"
}{
"table":"test",
"_id":1,
"result":"updated"
}OPTION clause is a Manticore-specific extension that lets you control a number of per-update options. The syntax is:
OPTION <optionname>=<value> [ , ... ]
The options are the same as for the SELECT statement. Specifically for the UPDATE statement, you can use these options:
- 'ignore_nonexistent_columns' - If set to 1, it indicates that the update will silently ignore any warnings about trying to update a column which does not exist in the current table schema. The default value is 0.
- 'strict' - This option is used in partial JSON attribute updates. By default (strict=1),
UPDATEwill result in an error if theUPDATEquery tries to perform an update on non-numeric properties. With strict=0, if multiple properties are updated and some are not allowed, theUPDATEwill not result in an error and will perform the changes only on allowed properties (with the rest being ignored). If none of theSETchanges of theUPDATEre permitted, the command will result in an error even with strict=0.
In rare cases, Manticore's built-in query analyzer may be incorrect in understanding a query and determining whether a table by ID should be used. This can result in poor performance for queries like UPDATE ... WHERE id = 123.
For information on how to force the optimizer to use a docid index, see Query optimizer hints.
Updates using HTTP JSON protocol are performed via the /update endpoint. The syntax is similar to the /insert endpoint, but this time the doc property is mandatory.
The server will respond with a JSON object stating if the operation was successful or not.
- JSON
POST /update
{
"table":"test",
"id":1,
"doc":
{
"gid" : 100,
"price" : 1000
}
}{
"table": "test",
"_id": 1,
"result": "updated"
}The ID of the document that needs to be updated can be set directly using the id property, as shown in the previous example, or you can update documents by query and apply the update to all the documents that match the query:
- JSON
POST /update
{
"table":"test",
"doc":
{
"price" : 1000
},
"query":
{
"match": { "*": "apple" }
}
}{
"table":"products",
"updated":1
}Синтаксис запроса такой же, как в /search endpoint. Обратите внимание, что нельзя указывать id и query одновременно.
FLUSH ATTRIBUTES
Команда FLUSH ATTRIBUTES гарантирует, что все обновления атрибутов в памяти во всех активных таблицах будут сброшены на диск. Она возвращает тег, который идентифицирует состояние результата на диске, представляющее количество фактических сохранений атрибутов на диск, выполненных с момента запуска сервера.
mysql> UPDATE testindex SET channel_id=1107025 WHERE id=1;
Query OK, 1 row affected (0.04 sec)
mysql> FLUSH ATTRIBUTES;
+------+
| tag |
+------+
| 1 |
+------+
1 row in set (0.19 sec)
См. также настройку attr_flush_period.
Вы можете выполнить несколько операций обновления в одном вызове, используя endpoint /bulk. Этот endpoint работает только с данными, у которых Content-Type установлен в application/x-ndjson. Данные должны быть отформатированы как JSON, разделённый переводами строк (NDJSON). По сути, это означает, что каждая строка должна содержать ровно одно JSON-выражение и заканчиваться переводом строки \n и, возможно, \r.
- JSON
POST /bulk
{ "update" : { "table" : "products", "id" : 1, "doc": { "price" : 10 } } }
{ "update" : { "table" : "products", "id" : 2, "doc": { "price" : 20 } } }{
"items":
[
{
"update":
{
"table":"products",
"_id":1,
"result":"updated"
}
},
{
"update":
{
"table":"products",
"_id":2,
"result":"updated"
}
}
],
"errors":false
}Endpoint /bulk поддерживает вставки, замены и удаления. Каждое выражение начинается с типа действия (в данном случае update). Вот список поддерживаемых действий:
insert: Вставляет документ. Синтаксис такой же, как в /insert endpoint.create: синоним дляinsertreplace: Заменяет документ. Синтаксис такой же, как в /replace.index: синоним дляreplaceupdate: Обновляет документ. Синтаксис такой же, как в /update.delete: Удаляет документ. Синтаксис такой же, как в /delete endpoint.
Также поддерживаются обновления по запросу и удаления по запросу.
- JSON
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
- TypeScript
- Go
POST /bulk
{ "update" : { "table" : "products", "doc": { "coeff" : 1000 }, "query": { "range": { "price": { "gte": 1000 } } } } }
{ "update" : { "table" : "products", "doc": { "coeff" : 0 }, "query": { "range": { "price": { "lt": 1000 } } } } }$client->bulk([
['update'=>[
'table' => 'products',
'doc' => [
'coeff' => 100
],
'query' => [
'range' => ['price'=>['gte'=>1000]]
]
]
],
['update'=>[
'table' => 'products',
'doc' => [
'coeff' => 0
],
'query' => [
'range' => ['price'=>['lt'=>1000]]
]
]
]
]);docs = [ \
{ "update" : { "table" : "products", "doc": { "coeff" : 1000 }, "query": { "range": { "price": { "gte": 1000 } } } } }, \
{ "update" : { "table" : "products", "doc": { "coeff" : 0 }, "query": { "range": { "price": { "lt": 1000 } } } } } ]
indexApi.bulk('\n'.join(map(json.dumps,docs)))docs = [ \
{ "update" : { "table" : "products", "doc": { "coeff" : 1000 }, "query": { "range": { "price": { "gte": 1000 } } } } }, \
{ "update" : { "table" : "products", "doc": { "coeff" : 0 }, "query": { "range": { "price": { "lt": 1000 } } } } } ]
await indexApi.bulk('\n'.join(map(json.dumps,docs)))docs = [
{ "update" : { "table" : "products", "doc": { "coeff" : 1000 }, "query": { "range": { "price": { "gte": 1000 } } } } },
{ "update" : { "table" : "products", "doc": { "coeff" : 0 }, "query": { "range": { "price": { "lt": 1000 } } } } } ];
res = await indexApi.bulk(docs.map(e=>JSON.stringify(e)).join('\n'));String body = "{ \"update\" : { \"index\" : \"products\", \"doc\": { \"coeff\" : 1000 }, \"query\": { \"range\": { \"price\": { \"gte\": 1000 } } } }} "+"\n"+
"{ \"update\" : { \"index\" : \"products\", \"doc\": { \"coeff\" : 0 }, \"query\": { \"range\": { \"price\": { \"lt\": 1000 } } } } }"+"\n";
indexApi.bulk(body);string body = "{ \"update\" : { \"index\" : \"products\", \"doc\": { \"coeff\" : 1000 }, \"query\": { \"range\": { \"price\": { \"gte\": 1000 } } } }} "+"\n"+
"{ \"update\" : { \"index\" : \"products\", \"doc\": { \"coeff\" : 0 }, \"query\": { \"range\": { \"price\": { \"lt\": 1000 } } } } }"+"\n";
indexApi.Bulk(body);string body = r#"{ "update" : { "index" : "products", "doc": { "coeff" : 1000 }, "query": { "range": { "price": { "gte": 1000 } } } }}
{ "update" : { "index" : "products", "doc": { "coeff" : 0 }, "query": { "range": { "price": { "lt": 1000 } } } } }
"#;
index_api.bulk(body).await;updateDocs = [
{
update: {
index: 'test',
id: 1,
doc: { content: 'Text 11', cat: 1, name: 'Doc 11' },
},
},
{
update: {
index: 'test',
id: 2,
doc: { content: 'Text 22', cat: 9, name: 'Doc 22' },
},
},
];
res = await indexApi.bulk(
updateDocs.map((e) => JSON.stringify(e)).join("\n")
);body := "{\"update\": {\"index\": \"test\", \"id\": 1, \"doc\": {\"content\": \"Text 11\", \"name\": \"Doc 11\", \"cat\": 1 }}}" + "\n" +
"{\"update\": {\"index\": \"test\", \"id\": 2, \"doc\": {\"content\": \"Text 22\", \"name\": \"Doc 22\", \"cat\": 9 }}}" +"\n";
res, _, _ := apiClient.IndexAPI.Bulk(context.Background()).Body(body).Execute(){
"items":
[
{
"update":
{
"table":"products",
"updated":1
}
},
{
"update":
{
"table":"products",
"updated":3
}
}
],
"errors":false
}Array(
[items] => Array (
Array(
[update] => Array(
[_index] => products
[updated] => 1
)
)
Array(
[update] => Array(
[_index] => products
[updated] => 3
)
)
){'error': None,
'items': [{u'update': {u'table': u'products', u'updated': 1}},
{u'update': {u'table': u'products', u'updated': 3}}]}{'error': None,
'items': [{u'update': {u'table': u'products', u'updated': 1}},
{u'update': {u'table': u'products', u'updated': 3}}]}{"items":[{"update":{"table":"products","updated":1}},{"update":{"table":"products","updated":3}}],"errors":false}class BulkResponse {
items: [{update={_index=products, _id=1, created=false, result=updated, status=200}}, {update={_index=products, _id=2, created=false, result=updated, status=200}}]
error: null
additionalProperties: {errors=false}
}class BulkResponse {
items: [{update={_index=products, _id=1, created=false, result=updated, status=200}}, {update={_index=products, _id=2, created=false, result=updated, status=200}}]
error: null
additionalProperties: {errors=false}
}class BulkResponse {
items: [{update={_index=products, _id=1, created=false, result=updated, status=200}}, {update={_index=products, _id=2, created=false, result=updated, status=200}}]
error: null
additionalProperties: {errors=false}
}{
"items":
[
{
"update":
{
"table":"test",
"updated":1
}
},
{
"update":
{
"table":"test",
"updated":1
}
}
],
"errors":false
}{
"items":
[
{
"update":
{
"table":"test",
"updated":1
}
},
{
"update":
{
"table":"test",
"updated":1
}
}
],
"errors":false
}Имейте в виду, что массовая операция останавливается при первом запросе, который приводит к ошибке.
attr_update_reserve=size
attr_update_reserve — это настройка на таблицу, которая определяет пространство, зарезервированное для обновлений блоб-атрибутов. Эта настройка необязательна, значение по умолчанию — 128k.
Когда блоб-атрибуты (MVAs, строки, JSON) обновляются, их длина может измениться. Если обновлённая строка (или MVA, или JSON) короче старой, она перезаписывает старую в файле .spb. Однако, если обновлённая строка длиннее, обновления записываются в конец файла .spb. Этот файл отображается в память, что означает, что изменение его размера может быть довольно медленным процессом, в зависимости от реализации отображения файлов в память в ОС.
Чтобы избежать частых изменений размера, вы можете указать дополнительное пространство, которое будет зарезервировано в конце файла .spb с помощью этой опции.
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
- TypeScript
- Go
- CONFIG
create table products(title text, price float) attr_update_reserve = '1M'POST /cli -d "
create table products(title text, price float) attr_update_reserve = '1M'"$params = [
'body' => [
'settings' => [
'attr_update_reserve' => '1M'
],
'columns' => [
'title'=>['type'=>'text'],
'price'=>['type'=>'float']
]
],
'table' => 'products'
];
$index = new \Manticoresearch\Index($client);
$index->create($params);utilsApi.sql('create table products(title text, price float) attr_update_reserve = \'1M\'')await utilsApi.sql('create table products(title text, price float) attr_update_reserve = \'1M\'')res = await utilsApi.sql('create table products(title text, price float) attr_update_reserve = \'1M\'');utilsApi.sql("create table products(title text, price float) attr_update_reserve = '1M'", true);utilsApi.Sql("create table products(title text, price float) attr_update_reserve = '1M'", true);utils_api.sql("create table products(title text, price float) attr_update_reserve = '1M'", Some(true)).await;utilsApi.sql("create table test(content text, name string, cat int) attr_update_reserve = '1M'");apiClient.UtilsAPI.Sql(context.Background()).Body("create table test(content text, name string, cat int) attr_update_reserve = '1M'").Execute()table products {
attr_update_reserve = 1M
type = rt
path = tbl
rt_field = title
rt_attr_uint = price
}attr_flush_period = 900 # persist updates to disk every 15 minutes
При обновлении атрибутов изменения сначала записываются в копию атрибутов в памяти. Эта настройка позволяет задать интервал между сбросами обновлений на диск. По умолчанию установлено 0, что отключает периодический сброс, но сброс всё равно происходит при нормальном завершении работы.