Document JSON format - Update

Vespa supports making changes to an existing document without submitting the entire document. This is called partial update. A partial update consists of the id of the existing document to update, and the operation or operations to perform on selected fields of the document.

Documents can be auto-created on updates using create if nonexistent. Also see conditional updates. All data structures (attribute, index and summary) are updatable. The following operations are supported:

All field types
  • assign (may also be used to clear fields)
Numeric field types
Composite types

assign

assign is used to completely replace the value of a field (or an element of a collection) with a new value. When replacing an entire field's value you can generally use the same syntax and structure as you would when feeding that field's value in a put operation.

Note: these examples are not exhaustive.

Single value field

field title type string {
  indexing: summary
}
{
    "update": "id:mynamespace:music::example",
    "fields": {
        "title": {
            "assign": "The best of Bob Dylan"
        }
    }
}

Tensor field

field tensorfield type tensor(x{},y{}) {
  indexing: attribute | summary
  attribute: tensor(x{},y{})
}
{
    "update": "id:mynamespace:tensordoctype::example",
    "fields": {
        "tensorfield": {
            "assign": {
                "cells": [
                    { "address": { "x": "a", "y": "b" }, "value": 2.0 },
                    { "address": { "x": "c", "y": "d" }, "value": 3.0 }
                ]
            }
        }
    }
}

Struct field

Replacing all fields in a struct

Entire struct fields may be replaced by assigning a JSON object of struct key/value pairs.

struct person {
  field first_name type string {}
  field last_name type string {}
}
field contact type person {
  indexing: summary
}
{
    "update": "id:mynamespace:workers::example",
    "fields": {
        "contact": {
            "assign": {
                "first_name": "Bob",
                "last_name": "The Plumber"
            }
        }
    }
}
Individual struct fields

Individual struct fields may be updated using field path syntax.

{
    "update": "id:mynamespace:workers::example",
    "fields": {
        "contact.first_name": { "assign": "Bob" },
        "contact.last_name": { "assign": "The Plumber" }
    }
}

Refer to the reference for restrictions using structs.

Map field

Individual map entries may be updated using field path syntax.

Assigning an element to a key in a map will insert the key/value mapping if it does not already exist, or overwrite it with the newly assigned value if it does exist.

Map to primitive value
field my_food_scores type map<string, string> {
  indexing: summary
}
{
    "update": "id:mynamespace:food::example",
    "fields": {
        "my_food_scores{Strawberries}": {
            "assign": "Delicious!"
        }
    }
}
Map to struct
struct contact_info {
  field phone_number type string {}
  field email type string {}
}
field contacts type map<string, contact_info> {
  indexing: summary
}
{
    "update": "id:mynamespace:people::d_duck",
    "fields": {
        "contacts{\"Uncle Scrooge\"}": {
            "assign": {
                "phone_number": "555-123-4567",
                "email": "number_one_dime_luvr1877@example.com"
            }
        }
    }
}

Refer to the reference for restrictions using maps.

Array field

Individual array elements may be updated using field path or match syntax

Array of primitive values
field ingredients type array<string> {
  indexing: summary
}
{
    "update": "id:mynamespace:cakes:tasty_chocolate_cake",
    "fields": {
        "ingredients[3]": {
            "assign": "2 cups of flour (editor's update: NOT asbestos!)"
        }
    }
}

Or alternatively:

{
    "update": "id:mynamespace:cakes:tasty_chocolate_cake",
    "fields": {
        "ingredients": {
            "match" {
                "element": 3,
                "assign": "2 cups of flour (editor's update: NOT asbestos!)"
            }
        }
    }
}
Array of structs
struct person {
  field first_name type string {}
  field last_name type string {}
}
field people type array<person> {
  indexing: summary
}
{
    "update": "id:mynamespace:students:example",
    "fields": {
        "people[34]": {
            "assign": {
                "first_name": "Bobby",
                "last_name": "Tables"
            }
        }
    }
}

Or alternatively:

{
    "update": "id:mynamespace:students:example",
    "fields": {
        "people": {
            "match": {
                "element": 34,
                "assign": {
                     "first_name": "Bobby",
                     "last_name": "Tables"
                }
            }
        }
    }
}

Refer to the reference for restrictions using array of structs.

Weighted set field

Adding new elements to a weighted set can be done using add, or by assigning with field{key} syntax. Example of the latter:

field int_weighted_set type weightedset<int> {
  indexing: summary
}
field string_weighted_set type weightedset<string> {
  indexing: summary
}
{
    "update":"id:weightedsetdoctype:weightedsetdoctype::example1",
    "fields": {
        "int_weighted_set{123}": {
            "assign": 123
        },
        "int_weighted_set{456}": {
            "assign": 100
        },
        "string_weighted_set{\"item 1\"}": {
            "assign": 144
        },
        "string_weighted_set{\"item 2\"}": {
            "assign": 7
        }
    }
}

Note that using the field{key} syntax for weighted sets may be less efficient than using add.

Clearing a field

To clear a field, assign a null value to it.

{
    "update": "id:mynamespace:music::example",
    "fields": {
        "title": {
            "assign": null
        }
    }
}

add

add is used to add entries to arrays or weighted sets.

Adding array elements

The added entries are appended to the end of the array in the order specified.

field tracks type array<string> {
  indexing: summary
}
{
    "update": "id:mynamespace:music::http://music.yahoo.com/bobdylan/BestOf",
    "fields": {
       "tracks": {
            "add": [
                "Lay Lady Lay",
                "Every Grain of Sand"
            ]
        }
    }
}

Adding weighted set entries

You can add weighted set elements using a JSON key/value syntax, where the value is the weight of the element.

Adding a key/weight mapping that already exists will overwrite the existing weight with the new one.

field int_weighted_set type weightedset<int> {
  indexing: summary
}
field string_weighted_set type weightedset<string> {
  indexing: summary
}
{
    "update":"id:weightedsetdoctype:weightedsetdoctype::example1",
    "fields": {
        "int_weighted_set":  {
            "add": {
                "123": 123,
                "456": 100
            }
        },
        "string_weighted_set": {
            "add": {
                "item 1": 144,
                "item 2": 7
            }
        }
    }
}

remove

You can remove elements from weighted sets and maps with remove.

Note: due to historical reasons, the syntax of the update differs slightly between the two.

Weighted set field
field string_weighted_set type weightedset<string> {
  indexing: summary
}
{
    "update":"id:mynamespace:weightedsetdoctype::example1",
    "fields":  {
        "string_weighted_set": {
            "remove": {
                "item 2": 0
            }
        }
    }
}
Map field
field string_map type map<string, string> {
  indexing: summary
}
{
    "update":"id:mynamespace:mapdoctype::example1",
    "fields":  {
        "string_map{item 2}": {
            "remove": 0
        }
    }
}

increment, decrement, multiply, divide

The four arithmetic operators increment, decrement, multiply and divide are used to modify single value numeric values without having to look up the current value before applying the update. Example:

field sales type int {
  indexing: summary | attribute
}
{
    "update": "id:music:music::http://music.yahoo.com/bobdylan/BestOf",
    "fields": {
        "sales": {
            "increment": 1
        }
    }
}

match

If an arithmetic operation is to be done for a specific key in a weighted set or array, use the match operation:

field track_popularity type weightedset<string> {
  indexing: summary | attribute
}
{
    "update": "id:music:music::http://music.yahoo.com/bobdylan/BestOf",
    "fields": {
        "track_popularity": {
            "match": {
                "element": "Lay Lady Lay",
                "increment": 1
            }
        }
    }
}

In other words, for the weighted set "track_popularity", match the element "Lay Lady Lay", then increment its weight by 1.

If the updated field were an array, the element value would be a positive integer.

Note: only one element can be matched per operation.

create (create if nonexistent)

Updates to nonexistent documents are supported using the create field. An empty document is created on the content nodes before the update is applied. This simplifies client code in the case of multiple writers:

{
    "update": "id:mynamespace:music::http://music.yahoo.com/bobdylan/BestOf",
    "create": true,
    "fields": {
        "title": {
            "assign": "The best of Bob Dylan"
        }
    }
}
Java example using the Document API:
public DocumentUpdate createUpdate(DocumentType musicType) {
  DocumentUpdate update = new DocumentUpdate(musicType, "id:mynamespace:music::http://music.yahoo.com/bobdylan/BestOf");
  update.setCreateIfNonExistent(true);
  return update;
}
Note: create cannot be used in combination with condition. This is because a condition can never match a document that does not exist, and since Vespa's eventual consistency model cannot safely make the decision to ignore this restriction on a per-replica level.

fieldpath

Fieldpath is for accessing fields within composite structures - for structures that are not part of index or attribute, it is possible to access elements directly using fieldpaths. This is done by adding more information to the field value. For map structures, specify the key (see example).

mymap{mykey}
and then do operation on the element which is keyed by "mykey". Arrays can be accessed as well (see details).
myarray[3]
And this is also true for structs (see details). Note: Struct updates do not work for index mode:
mystruct.value1
This also works for nested structures, e.g. a map of map to array of struct:
{
    "update": "id:mynamespace:complexdoctype::foo",
    "fields": {
        "nested_structure{firstMapKey}{secondMapKey}[4].title": {
            "assign": "Look at me, mom! I'm hiding deep in a nested type!"
        }
    }
}