# Updating Data

This chapter introduces how to use the database API to update data. We will continue to use the data used in the Reading Data chapter.

You can use two methods to update data:

API Description
update Partially update one or more records
set Replace and update a record

# Partial Update

Use the update method to partially update one or more records in a collection. A partial update means that only the specified fields will be updated, with no other fields affected.

For example, we can use the following code to set a to-do as finished:

db.collection('todos').doc('todo-identifiant-aleatoire').update({
  //Pass the data to be locally updated in "data"
  data: {
    // Indicates to set the done field as true
    done: true
  },
  success: function(res) {
    console.log(res.data)
  }
})

In addition to updating fields with specified values, the Database API also provides various update commands to perform more complex update operations. The update commands can be obtained via db.command:

Update Command Description
set Sets the field as specified value
remove Deletes field
inc Atomic auto-incrementing field value
mul Atomic auto-multiplying field value
push If the field value is an array, add a specified value to the end of the array
pop If the field value is an array, delete an element from the end of the array
shift If the field value is an array, delete an element from the head of the array
unshift If the field value is an array, add the specified value to the head of the array

For example, we can increase the progress of a to-do by 10%:

const _ = db.command
db.collection('todos').doc('todo-identifiant-aleatoire').update({
  data: {
    // Indicates that the database automatically increases the field by 10
    progress: _.inc(10)
  },
  success: function(res) {
    console.log(res.data)
  }
})

The advantage of using the inc command instead of fetching the value, adding 10, and then writing to the database is that such a write operation is an atomic operation and not affected by concurrent writes. For example, if users A and B fetch the same field value at the same time, then add 10 and 20 respectively, and write them into the database, the final result of this field will be increased by 20 instead of 30. This problem can be avoided if the inc command is used.

If the field is an array, we can use push, pop, shift, andunshift` to perform the atomic update operation on the array. For example, to add a tag to a to-do:

const _ = db.command
db.collection('todos').doc('todo-identifiant-aleatoire').update({
  data: {
    tags: _.push('mini-program')
  },
  success: function(res) {
    console.log(res.data)
  }
})

You may wonder what is the set command provided above used for? It is used to update a field value to another object. For example, the following statement updates the style.color field to 'blue', instead of updating the style field to a { color: 'blue' } object:

const _ = db.command
db.collection('todos').doc('todo-identifiant-aleatoire').update({
  data: {
    style: {
      color: 'blue'
    }
  },
  success: function(res) {
    console.log(res.data)
  }
})

You can uses the set command to update the style field to another object:

const _ = db.command
db.collection('todos').doc('todo-identifiant-aleatoire').update({
  data: {
    style: _.set({
      color: 'blue'
    })
  },
  success: function(res) {
    console.log(res.data)
  }
})

To update multiple data records, call the update method after the where statement on the server (cloud function). For example, to increase the progress of all unfinished to-dos by 10%:

// The async await syntax is used
const cloud = require('wx-server-sdk')
const db = cloud.database()
const _ = db.command

exports.main = async (event, context) => {
  try {
    return await db.collection('todos').where({
      done: false
    })
    .update({
      data: {
        progress: _.inc(10)
      },
    })
  } catch(e) {
    console.error(e)
  }
}

For details, refer to the Database APIs documentation.

# Replacing and Updating

You can use the set method to replace and update a record. Replacing and updating means to replace the specified record with the incoming object:

const _ = db.command
db.collection('todos').doc('todo-identifiant-aleatoire').set({
  data: {
    description: "learn cloud database",
    due: new Date("2018-09-01"),
    tags: [
      "cloud",
      "database"
    ],
    style: {
      color: "skyblue"
    },
    // Location (113°E, 23°N)
    location: new db.Geo.Point(113, 23),
    done: false
  },
  success: function(res) {
    console.log(res.data)
  }
})

If a record with the specified ID does not exist, the record will be automatically created with the specified ID.

In the next chapter, we will learn how to delete records.