Saving Data

This document covers the four methods for writing data to your Firebase Realtime Database : set, update, push, and transactions support.

Ways to Save Data

set Write or replace data to a defined path, like messages/users/<username>
update Update some of the keys for a defined path without replacing all of the data
push Add to a list of datain the database. Every time you push a new node onto a list, your database generates a unique key, like messages/users/<unique-user-id>/<username>
transaction Use transactions when working with complex data that could be corrupted by concurrent updates

Saving Data

The basic database write operation is a set which saves new data to the specified database reference, replacing any existing data at that path. To understand set, we'll build a simple blogging app. The data for your app is stored at this database reference:

Java
 final 
  
 FirebaseDatabase 
  
 database 
  
 = 
  
 FirebaseDatabase 
 . 
 getInstance 
 (); 
 DatabaseReference 
  
 ref 
  
 = 
  
 database 
 . 
 getReference 
 ( 
 "server/saving-data/fireblog" 
 ); 
Node.js
 // Import Admin SDK 
 const 
  
 { 
  
 getDatabase 
  
 } 
  
 = 
  
 require 
 ( 
 'firebase-admin/database' 
 ); 
 // Get a database reference to our blog 
 const 
  
 db 
  
 = 
  
 getDatabase 
 (); 
 const 
  
 ref 
  
 = 
  
 db 
 . 
 ref 
 ( 
 'server/saving-data/fireblog' 
 ); 
Python
 # Import database module. 
 from 
  
 firebase_admin 
  
 import 
 db 
 # Get a database reference to our blog. 
 ref 
 = 
 db 
 . 
 reference 
 ( 
 'server/saving-data/fireblog' 
 ) 
Go
 // Create a database client from App. 
 client 
 , 
  
 err 
  
 := 
  
 app 
 . 
 Database 
 ( 
 ctx 
 ) 
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 log 
 . 
 Fatalln 
 ( 
 "Error initializing database client:" 
 , 
  
 err 
 ) 
 } 
 // Get a database reference to our blog. 
 ref 
  
 := 
  
 client 
 . 
 NewRef 
 ( 
 "server/saving-data/fireblog" 
 ) 

Let's start by saving some user data. We'll store each user by a unique username, and we'll also store their full name and date of birth. Since each user will have a unique username, it makes sense to use the set method here instead of the push method since you already have the key and don't need to create one.

First, create a database reference to your user data. Then use set() / setValue() to save a user object to the database with the user's username, full name, and birthday. You can pass set a string, number, boolean, null , array or any JSON object. Passing null will remove the data at the specified location. In this case you'll pass it an object:

Java
 public 
  
 static 
  
 class 
 User 
  
 { 
  
 public 
  
 String 
  
 date_of_birth 
 ; 
  
 public 
  
 String 
  
 full_name 
 ; 
  
 public 
  
 String 
  
 nickname 
 ; 
  
 public 
  
 User 
 ( 
 String 
  
 dateOfBirth 
 , 
  
 String 
  
 fullName 
 ) 
  
 { 
  
 // ... 
  
 } 
  
 public 
  
 User 
 ( 
 String 
  
 dateOfBirth 
 , 
  
 String 
  
 fullName 
 , 
  
 String 
  
 nickname 
 ) 
  
 { 
  
 // ... 
  
 } 
 } 
 DatabaseReference 
  
 usersRef 
  
 = 
  
 ref 
 . 
 child 
 ( 
 "users" 
 ); 
 Map<String 
 , 
  
 User 
>  
 users 
  
 = 
  
 new 
  
 HashMap 
<> (); 
 users 
 . 
 put 
 ( 
 "alanisawesome" 
 , 
  
 new 
  
 User 
 ( 
 "June 23, 1912" 
 , 
  
 "Alan Turing" 
 )); 
 users 
 . 
 put 
 ( 
 "gracehop" 
 , 
  
 new 
  
 User 
 ( 
 "December 9, 1906" 
 , 
  
 "Grace Hopper" 
 )); 
 usersRef 
 . 
 setValueAsync 
 ( 
 users 
 ); 
Node.js
 const 
  
 usersRef 
  
 = 
  
 ref 
 . 
 child 
 ( 
 'users' 
 ); 
 usersRef 
 . 
 set 
 ({ 
  
 alanisawesome 
 : 
  
 { 
  
 date_of_birth 
 : 
  
 'June 23, 1912' 
 , 
  
 full_name 
 : 
  
 'Alan Turing' 
  
 }, 
  
 gracehop 
 : 
  
 { 
  
 date_of_birth 
 : 
  
 'December 9, 1906' 
 , 
  
 full_name 
 : 
  
 'Grace Hopper' 
  
 } 
 }); 
Python
 users_ref 
 = 
 ref 
 . 
 child 
 ( 
 'users' 
 ) 
 users_ref 
 . 
 set 
 ({ 
 'alanisawesome' 
 : 
 { 
 'date_of_birth' 
 : 
 'June 23, 1912' 
 , 
 'full_name' 
 : 
 'Alan Turing' 
 }, 
 'gracehop' 
 : 
 { 
 'date_of_birth' 
 : 
 'December 9, 1906' 
 , 
 'full_name' 
 : 
 'Grace Hopper' 
 } 
 }) 
Go
 // User is a json-serializable type. 
 type 
  
 User 
  
 struct 
  
 { 
  
 DateOfBirth 
  
 string 
  
 `json:"date_of_birth,omitempty"` 
  
 FullName 
  
 string 
  
 `json:"full_name,omitempty"` 
  
 Nickname 
  
 string 
  
 `json:"nickname,omitempty"` 
 } 
 usersRef 
  
 := 
  
 ref 
 . 
 Child 
 ( 
 "users" 
 ) 
 err 
  
 := 
  
 usersRef 
 . 
 Set 
 ( 
 ctx 
 , 
  
 map 
 [ 
 string 
 ] 
 * 
 User 
 { 
  
 "alanisawesome" 
 : 
  
 { 
  
 DateOfBirth 
 : 
  
 "June 23, 1912" 
 , 
  
 FullName 
 : 
  
 "Alan Turing" 
 , 
  
 }, 
  
 "gracehop" 
 : 
  
 { 
  
 DateOfBirth 
 : 
  
 "December 9, 1906" 
 , 
  
 FullName 
 : 
  
 "Grace Hopper" 
 , 
  
 }, 
 }) 
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 log 
 . 
 Fatalln 
 ( 
 "Error setting value:" 
 , 
  
 err 
 ) 
 } 

When a JSON object is saved to the database, the object properties are automatically mapped to database child locations in a nested fashion. Now if you navigate to the URL https://docs-examples.firebaseio.com/server/saving-data/fireblog/users/alanisawesome/full_name , we'll see the value "Alan Turing". You can also save data directly to a child location:

Java
 usersRef 
 . 
 child 
 ( 
 "alanisawesome" 
 ). 
 setValueAsync 
 ( 
 new 
  
 User 
 ( 
 "June 23, 1912" 
 , 
  
 "Alan Turing" 
 )); 
 usersRef 
 . 
 child 
 ( 
 "gracehop" 
 ). 
 setValueAsync 
 ( 
 new 
  
 User 
 ( 
 "December 9, 1906" 
 , 
  
 "Grace Hopper" 
 )); 
Node.js
 const 
  
 usersRef 
  
 = 
  
 ref 
 . 
 child 
 ( 
 'users' 
 ); 
 usersRef 
 . 
 child 
 ( 
 'alanisawesome' 
 ). 
 set 
 ({ 
  
 date_of_birth 
 : 
  
 'June 23, 1912' 
 , 
  
 full_name 
 : 
  
 'Alan Turing' 
 }); 
 usersRef 
 . 
 child 
 ( 
 'gracehop' 
 ). 
 set 
 ({ 
  
 date_of_birth 
 : 
  
 'December 9, 1906' 
 , 
  
 full_name 
 : 
  
 'Grace Hopper' 
 }); 
Python
 users_ref 
 . 
 child 
 ( 
 'alanisawesome' 
 ) 
 . 
 set 
 ({ 
 'date_of_birth' 
 : 
 'June 23, 1912' 
 , 
 'full_name' 
 : 
 'Alan Turing' 
 }) 
 users_ref 
 . 
 child 
 ( 
 'gracehop' 
 ) 
 . 
 set 
 ({ 
 'date_of_birth' 
 : 
 'December 9, 1906' 
 , 
 'full_name' 
 : 
 'Grace Hopper' 
 }) 
Go
 if 
  
 err 
  
 := 
  
 usersRef 
 . 
 Child 
 ( 
 "alanisawesome" 
 ). 
 Set 
 ( 
 ctx 
 , 
  
& User 
 { 
  
 DateOfBirth 
 : 
  
 "June 23, 1912" 
 , 
  
 FullName 
 : 
  
 "Alan Turing" 
 , 
 }); 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 log 
 . 
 Fatalln 
 ( 
 "Error setting value:" 
 , 
  
 err 
 ) 
 } 
 if 
  
 err 
  
 := 
  
 usersRef 
 . 
 Child 
 ( 
 "gracehop" 
 ). 
 Set 
 ( 
 ctx 
 , 
  
& User 
 { 
  
 DateOfBirth 
 : 
  
 "December 9, 1906" 
 , 
  
 FullName 
 : 
  
 "Grace Hopper" 
 , 
 }); 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 log 
 . 
 Fatalln 
 ( 
 "Error setting value:" 
 , 
  
 err 
 ) 
 } 

The above two examples - writing both values at the same time as an object and writing them separately to child locations - will result in the same data being saved to your database:

{
  "users": {
    "alanisawesome": {
      "date_of_birth": "June 23, 1912",
      "full_name": "Alan Turing"
    },
    "gracehop": {
      "date_of_birth": "December 9, 1906",
      "full_name": "Grace Hopper"
    }
  }
}

The first example will only trigger one event on clients that are watching the data, whereas the second example will trigger two. It is important to note that if data already existed at usersRef , the first approach would overwrite it, but the second method would only modify the value of each separate child node while leaving other children of usersRef unchanged.

Updating Saved Data

If you want to write to multiple children of a database location at the same time without overwriting other child nodes, you can use the update method as shown below:

Java
 DatabaseReference 
  
 hopperRef 
  
 = 
  
 usersRef 
 . 
 child 
 ( 
 "gracehop" 
 ); 
 Map<String 
 , 
  
 Object 
>  
 hopperUpdates 
  
 = 
  
 new 
  
 HashMap 
<> (); 
 hopperUpdates 
 . 
 put 
 ( 
 "nickname" 
 , 
  
 "Amazing Grace" 
 ); 
 hopperRef 
 . 
 updateChildrenAsync 
 ( 
 hopperUpdates 
 ); 
Node.js
 const 
  
 usersRef 
  
 = 
  
 ref 
 . 
 child 
 ( 
 'users' 
 ); 
 const 
  
 hopperRef 
  
 = 
  
 usersRef 
 . 
 child 
 ( 
 'gracehop' 
 ); 
 hopperRef 
 . 
 update 
 ({ 
  
 'nickname' 
 : 
  
 'Amazing Grace' 
 }); 
Python
 hopper_ref 
 = 
 users_ref 
 . 
 child 
 ( 
 'gracehop' 
 ) 
 hopper_ref 
 . 
 update 
 ({ 
 'nickname' 
 : 
 'Amazing Grace' 
 }) 
Go
 hopperRef 
  
 := 
  
 usersRef 
 . 
 Child 
 ( 
 "gracehop" 
 ) 
 if 
  
 err 
  
 := 
  
 hopperRef 
 . 
 Update 
 ( 
 ctx 
 , 
  
 map 
 [ 
 string 
 ] 
 interface 
 {}{ 
  
 "nickname" 
 : 
  
 "Amazing Grace" 
 , 
 }); 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 log 
 . 
 Fatalln 
 ( 
 "Error updating child:" 
 , 
  
 err 
 ) 
 } 

This will update Grace's data to include her nickname. If you had used set here instead of update, it would have deleted both full_name and date_of_birth from your hopperRef .

The Firebase Realtime Database also supports multi-path updates. This means that update can now update values at multiple locations in your database at the same time, a powerful feature which allows helps you denormalize your data . Using multi-path updates, you can add nicknames to both Grace and Alan at the same time:

Java
 Map<String 
 , 
  
 Object 
>  
 userUpdates 
  
 = 
  
 new 
  
 HashMap 
<> (); 
 userUpdates 
 . 
 put 
 ( 
 "alanisawesome/nickname" 
 , 
  
 "Alan The Machine" 
 ); 
 userUpdates 
 . 
 put 
 ( 
 "gracehop/nickname" 
 , 
  
 "Amazing Grace" 
 ); 
 usersRef 
 . 
 updateChildrenAsync 
 ( 
 userUpdates 
 ); 
Node.js
 const 
  
 usersRef 
  
 = 
  
 ref 
 . 
 child 
 ( 
 'users' 
 ); 
 usersRef 
 . 
 update 
 ({ 
  
 'alanisawesome/nickname' 
 : 
  
 'Alan The Machine' 
 , 
  
 'gracehop/nickname' 
 : 
  
 'Amazing Grace' 
 }); 
Python
 users_ref 
 . 
 update 
 ({ 
 'alanisawesome/nickname' 
 : 
 'Alan The Machine' 
 , 
 'gracehop/nickname' 
 : 
 'Amazing Grace' 
 }) 
Go
 if 
  
 err 
  
 := 
  
 usersRef 
 . 
 Update 
 ( 
 ctx 
 , 
  
 map 
 [ 
 string 
 ] 
 interface 
 {}{ 
  
 "alanisawesome/nickname" 
 : 
  
 "Alan The Machine" 
 , 
  
 "gracehop/nickname" 
 : 
  
 "Amazing Grace" 
 , 
 }); 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 log 
 . 
 Fatalln 
 ( 
 "Error updating children:" 
 , 
  
 err 
 ) 
 } 

After this update, both Alan and Grace have had their nicknames added:

{
  "users": {
    "alanisawesome": {
      "date_of_birth": "June 23, 1912",
      "full_name": "Alan Turing",
      "nickname": "Alan The Machine"
    },
    "gracehop": {
      "date_of_birth": "December 9, 1906",
      "full_name": "Grace Hopper",
      "nickname": "Amazing Grace"
    }
  }
}

Note that trying to update objects by writing objects with the paths included will result in different behavior. Let's take a look at what happens if you instead try to update Grace and Alan this way:

Java
 Map<String 
 , 
  
 Object 
>  
 userNicknameUpdates 
  
 = 
  
 new 
  
 HashMap 
<> (); 
 userNicknameUpdates 
 . 
 put 
 ( 
 "alanisawesome" 
 , 
  
 new 
  
 User 
 ( 
 null 
 , 
  
 null 
 , 
  
 "Alan The Machine" 
 )); 
 userNicknameUpdates 
 . 
 put 
 ( 
 "gracehop" 
 , 
  
 new 
  
 User 
 ( 
 null 
 , 
  
 null 
 , 
  
 "Amazing Grace" 
 )); 
 usersRef 
 . 
 updateChildrenAsync 
 ( 
 userNicknameUpdates 
 ); 
Node.js
 const 
  
 usersRef 
  
 = 
  
 ref 
 . 
 child 
 ( 
 'users' 
 ); 
 usersRef 
 . 
 update 
 ({ 
  
 'alanisawesome' 
 : 
  
 { 
  
 'nickname' 
 : 
  
 'Alan The Machine' 
  
 }, 
  
 'gracehop' 
 : 
  
 { 
  
 'nickname' 
 : 
  
 'Amazing Grace' 
  
 } 
 }); 
Python
 users_ref 
 . 
 update 
 ({ 
 'alanisawesome' 
 : 
 { 
 'nickname' 
 : 
 'Alan The Machine' 
 }, 
 'gracehop' 
 : 
 { 
 'nickname' 
 : 
 'Amazing Grace' 
 } 
 }) 
Go
 if 
  
 err 
  
 := 
  
 usersRef 
 . 
 Update 
 ( 
 ctx 
 , 
  
 map 
 [ 
 string 
 ] 
 interface 
 {}{ 
  
 "alanisawesome" 
 : 
  
& User 
 { 
 Nickname 
 : 
  
 "Alan The Machine" 
 }, 
  
 "gracehop" 
 : 
  
& User 
 { 
 Nickname 
 : 
  
 "Amazing Grace" 
 }, 
 }); 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 log 
 . 
 Fatalln 
 ( 
 "Error updating children:" 
 , 
  
 err 
 ) 
 } 

This results in different behavior, namely overwriting the entire /users node:

{
  "users": {
    "alanisawesome": {
      "nickname": "Alan The Machine"
    },
    "gracehop": {
      "nickname": "Amazing Grace"
    }
  }
}

Adding a Completion Callback

In Node.js and Java Admin SDKs, if you'd like to know when your data has been committed, you can add a completion callback. Both set and update methods in these SDKs take an optional completion callback that is called when the write has been committed to the database. If the call was unsuccessful for some reason, the callback is passed an error object indicating why the failure occurred. In Python and Go Admin SDKs, all write methods are blocking. That is, the write methods do not return until the writes are committed to the database.

Java
 DatabaseReference 
  
 dataRef 
  
 = 
  
 ref 
 . 
 child 
 ( 
 "data" 
 ); 
 dataRef 
 . 
 setValue 
 ( 
 "I'm writing data" 
 , 
  
 new 
  
 DatabaseReference 
 . 
 CompletionListener 
 () 
  
 { 
  
 @Override 
  
 public 
  
 void 
  
 onComplete 
 ( 
 DatabaseError 
  
 databaseError 
 , 
  
 DatabaseReference 
  
 databaseReference 
 ) 
  
 { 
  
 if 
  
 ( 
 databaseError 
  
 != 
  
 null 
 ) 
  
 { 
  
 System 
 . 
 out 
 . 
 println 
 ( 
 "Data could not be saved " 
  
 + 
  
 databaseError 
 . 
 getMessage 
 ()); 
  
 } 
  
 else 
  
 { 
  
 System 
 . 
 out 
 . 
 println 
 ( 
 "Data saved successfully." 
 ); 
  
 } 
  
 } 
 }); 
Node.js
 dataRef 
 . 
 set 
 ( 
 'I\'m writing data' 
 , 
  
 ( 
 error 
 ) 
  
 = 
>  
 { 
  
 if 
  
 ( 
 error 
 ) 
  
 { 
  
 console 
 . 
 log 
 ( 
 'Data could not be saved.' 
  
 + 
  
 error 
 ); 
  
 } 
  
 else 
  
 { 
  
 console 
 . 
 log 
 ( 
 'Data saved successfully.' 
 ); 
  
 } 
 }); 

Saving Lists of Data

When creating lists of data, it is important to keep in mind the multi-user nature of most applications and adjust your list structure accordingly. Expanding on the example above, let's add blog posts to your app. Your first instinct might be to use set to store children with auto-incrementing integer indexes, like the following:

 // NOT RECOMMENDED - use push() instead! 
 { 
  
 "posts" 
 : 
  
 { 
  
 "0" 
 : 
  
 { 
  
 "author" 
 : 
  
 "gracehop" 
 , 
  
 "title" 
 : 
  
 "Announcing COBOL, a New Programming Language" 
  
 }, 
  
 "1" 
 : 
  
 { 
  
 "author" 
 : 
  
 "alanisawesome" 
 , 
  
 "title" 
 : 
  
 "The Turing Machine" 
  
 } 
  
 } 
 } 

If a user adds a new post it would be stored as /posts/2 . This would work if only a single author were adding posts, but in your collaborative blogging application many users may add posts at the same time. If two authors write to /posts/2 simultaneously, then one of the posts would be deleted by the other.

To solve this, the Firebase clients provide a push() function that generates a unique key for each new child. By using unique child keys, several clients can add children to the same location at the same time without worrying about write conflicts.

Java
 public 
  
 static 
  
 class 
 Post 
  
 { 
  
 public 
  
 String 
  
 author 
 ; 
  
 public 
  
 String 
  
 title 
 ; 
  
 public 
  
 Post 
 ( 
 String 
  
 author 
 , 
  
 String 
  
 title 
 ) 
  
 { 
  
 // ... 
  
 } 
 } 
 DatabaseReference 
  
 postsRef 
  
 = 
  
 ref 
 . 
 child 
 ( 
 "posts" 
 ); 
 DatabaseReference 
  
 newPostRef 
  
 = 
  
 postsRef 
 . 
 push 
 (); 
 newPostRef 
 . 
 setValueAsync 
 ( 
 new 
  
 Post 
 ( 
 "gracehop" 
 , 
  
 "Announcing COBOL, a New Programming Language" 
 )); 
 // We can also chain the two calls together 
 postsRef 
 . 
 push 
 (). 
 setValueAsync 
 ( 
 new 
  
 Post 
 ( 
 "alanisawesome" 
 , 
  
 "The Turing Machine" 
 )); 
Node.js
 const 
  
 newPostRef 
  
 = 
  
 postsRef 
 . 
 push 
 (); 
 newPostRef 
 . 
 set 
 ({ 
  
 author 
 : 
  
 'gracehop' 
 , 
  
 title 
 : 
  
 'Announcing COBOL, a New Programming Language' 
 }); 
 // we can also chain the two calls together 
 postsRef 
 . 
 push 
 (). 
 set 
 ({ 
  
 author 
 : 
  
 'alanisawesome' 
 , 
  
 title 
 : 
  
 'The Turing Machine' 
 }); 
Python
 posts_ref 
 = 
 ref 
 . 
 child 
 ( 
 'posts' 
 ) 
 new_post_ref 
 = 
 posts_ref 
 . 
 push 
 () 
 new_post_ref 
 . 
 set 
 ({ 
 'author' 
 : 
 'gracehop' 
 , 
 'title' 
 : 
 'Announcing COBOL, a New Programming Language' 
 }) 
 # We can also chain the two calls together 
 posts_ref 
 . 
 push 
 () 
 . 
 set 
 ({ 
 'author' 
 : 
 'alanisawesome' 
 , 
 'title' 
 : 
 'The Turing Machine' 
 }) 
Go
 // Post is a json-serializable type. 
 type 
  
 Post 
  
 struct 
  
 { 
  
 Author 
  
 string 
  
 `json:"author,omitempty"` 
  
 Title 
  
 string 
  
 `json:"title,omitempty"` 
 } 
 postsRef 
  
 := 
  
 ref 
 . 
 Child 
 ( 
 "posts" 
 ) 
 newPostRef 
 , 
  
 err 
  
 := 
  
 postsRef 
 . 
 Push 
 ( 
 ctx 
 , 
  
 nil 
 ) 
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 log 
 . 
 Fatalln 
 ( 
 "Error pushing child node:" 
 , 
  
 err 
 ) 
 } 
 if 
  
 err 
  
 := 
  
 newPostRef 
 . 
 Set 
 ( 
 ctx 
 , 
  
& Post 
 { 
  
 Author 
 : 
  
 "gracehop" 
 , 
  
 Title 
 : 
  
 "Announcing COBOL, a New Programming Language" 
 , 
 }); 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 log 
 . 
 Fatalln 
 ( 
 "Error setting value:" 
 , 
  
 err 
 ) 
 } 
 // We can also chain the two calls together 
 if 
  
 _ 
 , 
  
 err 
  
 := 
  
 postsRef 
 . 
 Push 
 ( 
 ctx 
 , 
  
& Post 
 { 
  
 Author 
 : 
  
 "alanisawesome" 
 , 
  
 Title 
 : 
  
 "The Turing Machine" 
 , 
 }); 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 log 
 . 
 Fatalln 
 ( 
 "Error pushing child node:" 
 , 
  
 err 
 ) 
 } 

The unique key is based on a timestamp, so list items will automatically be ordered chronologically. Because Firebase generates a unique key for each blog post, no write conflicts will occur if multiple users add a post at the same time. Your database data now looks like this:

{
  "posts": {
    "-JRHTHaIs-jNPLXOQivY": {
      "author": "gracehop",
      "title": "Announcing COBOL, a New Programming Language"
    },
    "-JRHTHaKuITFIhnj02kE": {
      "author": "alanisawesome",
      "title": "The Turing Machine"
    }
  }
}

In JavaScript, Python and Go, the pattern of calling push() and then immediately calling set() is so common that the Firebase SDK lets you combine them by passing the data to be set directly to push() as follows:

Java
 // No Java equivalent 
Node.js
 // This is equivalent to the calls to push().set(...) above 
 postsRef 
 . 
 push 
 ({ 
  
 author 
 : 
  
 'gracehop' 
 , 
  
 title 
 : 
  
 'Announcing COBOL, a New Programming Language' 
 });; 
Python
 # This is equivalent to the calls to push().set(...) above 
 posts_ref 
 . 
 push 
 ({ 
 'author' 
 : 
 'gracehop' 
 , 
 'title' 
 : 
 'Announcing COBOL, a New Programming Language' 
 }) 
Go
 if 
  
 _ 
 , 
  
 err 
  
 := 
  
 postsRef 
 . 
 Push 
 ( 
 ctx 
 , 
  
& Post 
 { 
  
 Author 
 : 
  
 "gracehop" 
 , 
  
 Title 
 : 
  
 "Announcing COBOL, a New Programming Language" 
 , 
 }); 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 log 
 . 
 Fatalln 
 ( 
 "Error pushing child node:" 
 , 
  
 err 
 ) 
 } 

Getting the unique key generated by push()

Calling push() will return a reference to the new data path, which you can use to get the key or set data to it. The following code will result in the same data as the above example, but now we'll have access to the unique key that was generated:

Java
 // Generate a reference to a new location and add some data using push() 
 DatabaseReference 
  
 pushedPostRef 
  
 = 
  
 postsRef 
 . 
 push 
 (); 
 // Get the unique ID generated by a push() 
 String 
  
 postId 
  
 = 
  
 pushedPostRef 
 . 
 getKey 
 (); 
Node.js
 // Generate a reference to a new location and add some data using push() 
 const 
  
 newPostRef 
  
 = 
  
 postsRef 
 . 
 push 
 (); 
 // Get the unique key generated by push() 
 const 
  
 postId 
  
 = 
  
 newPostRef 
 . 
 key 
 ; 
Python
 # Generate a reference to a new location and add some data using push() 
 new_post_ref 
 = 
 posts_ref 
 . 
 push 
 () 
 # Get the unique key generated by push() 
 post_id 
 = 
 new_post_ref 
 . 
 key 
Go
 // Generate a reference to a new location and add some data using Push() 
 newPostRef 
 , 
  
 err 
  
 := 
  
 postsRef 
 . 
 Push 
 ( 
 ctx 
 , 
  
 nil 
 ) 
 if 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 log 
 . 
 Fatalln 
 ( 
 "Error pushing child node:" 
 , 
  
 err 
 ) 
 } 
 // Get the unique key generated by Push() 
 postID 
  
 := 
  
 newPostRef 
 . 
 Key 

As you can see, you can get the value of the unique key from your push() reference.

In the next section on Retrieving Data , we'll learn how to read this data from a Firebase database.

Saving Transactional Data

When working with complex data that could be corrupted by concurrent modifications, such as incremental counters, the SDK provides a transaction operation .

In Java and Node.js, you give the transaction operation two callbacks: an update function and an optional completion callback. In Python and Go, the transaction operation is blocking and therefore it only accepts the update function.

The update function takes the current state of the data as an argument and should return the new desired state you would like to write. For example, if you wanted to increment the number of upvotes on a specific blog post, you would write a transaction like the following:

Java
 DatabaseReference 
  
 upvotesRef 
  
 = 
  
 ref 
 . 
 child 
 ( 
 "server/saving-data/fireblog/posts/-JRHTHaIs-jNPLXOQivY/upvotes" 
 ); 
 upvotesRef 
 . 
 runTransaction 
 ( 
 new 
  
 Transaction 
 . 
 Handler 
 () 
  
 { 
  
 @Override 
  
 public 
  
 Transaction 
 . 
 Result 
  
 doTransaction 
 ( 
 MutableData 
  
 mutableData 
 ) 
  
 { 
  
 Integer 
  
 currentValue 
  
 = 
  
 mutableData 
 . 
 getValue 
 ( 
 Integer 
 . 
 class 
 ); 
  
 if 
  
 ( 
 currentValue 
  
 == 
  
 null 
 ) 
  
 { 
  
 mutableData 
 . 
 setValue 
 ( 
 1 
 ); 
  
 } 
  
 else 
  
 { 
  
 mutableData 
 . 
 setValue 
 ( 
 currentValue 
  
 + 
  
 1 
 ); 
  
 } 
  
 return 
  
 Transaction 
 . 
 success 
 ( 
 mutableData 
 ); 
  
 } 
  
 @Override 
  
 public 
  
 void 
  
 onComplete 
 ( 
  
 DatabaseError 
  
 databaseError 
 , 
  
 boolean 
  
 committed 
 , 
  
 DataSnapshot 
  
 dataSnapshot 
 ) 
  
 { 
  
 System 
 . 
 out 
 . 
 println 
 ( 
 "Transaction completed" 
 ); 
  
 } 
 }); 
Node.js
 const 
  
 upvotesRef 
  
 = 
  
 db 
 . 
 ref 
 ( 
 'server/saving-data/fireblog/posts/-JRHTHaIs-jNPLXOQivY/upvotes' 
 ); 
 upvotesRef 
 . 
 transaction 
 (( 
 current_value 
 ) 
  
 = 
>  
 { 
  
 return 
  
 ( 
 current_value 
  
 || 
  
 0 
 ) 
  
 + 
  
 1 
 ; 
 }); 
Python
 def 
  
 increment_votes 
 ( 
 current_value 
 ): 
 return 
 current_value 
 + 
 1 
 if 
 current_value 
 else 
 1 
 upvotes_ref 
 = 
 db 
 . 
 reference 
 ( 
 'server/saving-data/fireblog/posts/-JRHTHaIs-jNPLXOQivY/upvotes' 
 ) 
 try 
 : 
 new_vote_count 
 = 
 upvotes_ref 
 . 
 transaction 
 ( 
 increment_votes 
 ) 
 print 
 ( 
 'Transaction completed' 
 ) 
 except 
 db 
 . 
 TransactionAbortedError 
 : 
 print 
 ( 
 'Transaction failed to commit' 
 ) 
Go
 fn 
  
 := 
  
 func 
 ( 
 t 
  
 db 
 . 
 TransactionNode 
 ) 
  
 ( 
 interface 
 {}, 
  
 error 
 ) 
  
 { 
  
 var 
  
 currentValue 
  
 int 
  
 if 
  
 err 
  
 := 
  
 t 
 . 
 Unmarshal 
 ( 
& currentValue 
 ); 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 return 
  
 nil 
 , 
  
 err 
  
 } 
  
 return 
  
 currentValue 
  
 + 
  
 1 
 , 
  
 nil 
 } 
 ref 
  
 := 
  
 client 
 . 
 NewRef 
 ( 
 "server/saving-data/fireblog/posts/-JRHTHaIs-jNPLXOQivY/upvotes" 
 ) 
 if 
  
 err 
  
 := 
  
 ref 
 . 
 Transaction 
 ( 
 ctx 
 , 
  
 fn 
 ); 
  
 err 
  
 != 
  
 nil 
  
 { 
  
 log 
 . 
 Fatalln 
 ( 
 "Transaction failed to commit:" 
 , 
  
 err 
 ) 
 } 

The above example checks to see if the counter is null or hasn't been incremented yet, since transactions can be called with null if no default value was written.

If the above code had been run without a transaction function and two clients attempted to increment it simultaneously, they would both write 1 as the new value, resulting in one increment instead of two.

Network Connectivity and Offline Writes

Firebase Node.js and Java clients maintain their own internal version of any active data. When data is written, it is written to this local version first. The client then synchronizes that data with the database and with other clients on a 'best-effort' basis.

As a result, all writes to the database will trigger local events immediately, before any data has even been written to the database. This means that when you write an application using Firebase, your app will remain responsive regardless of network latency or Internet connectivity.

Once connectivity is reestablished, we'll receive the appropriate set of events so that the client "catches up" with the current server state, without having to write any custom code.

Securing Your Data

The Firebase Realtime Database has a security language that lets you define which users have read and write access to different nodes of your data. You can read more about it in Secure Your Data .

Create a Mobile Website
View Site in Mobile | Classic
Share by: