หน้านี้ได้รับการแปลโดย Cloud Translation API
Switch to English

กำลังบันทึกข้อมูล

เอกสารนี้ครอบคลุมสี่วิธีในการเขียนข้อมูลไปยังฐานข้อมูล Firebase Realtime ของคุณ: รองรับการตั้งค่าการอัพเดทแบบพุชและการทำธุรกรรม

วิธีในการบันทึกข้อมูล

ชุด เขียนหรือแทนที่ข้อมูลไปยัง เส้นทางที่กำหนด เช่น messages/users/<username>
ปรับปรุง อัปเดตบางคีย์สำหรับเส้นทางที่กำหนดโดยไม่ต้องแทนที่ข้อมูลทั้งหมด
ดัน เพิ่มลงในรายการข้อมูล ในฐานข้อมูล ทุกครั้งที่คุณส่งโหนดใหม่ไปยังรายการฐานข้อมูลของคุณจะสร้างคีย์เฉพาะเช่น messages/users/<unique-user-id>/<username>
การซื้อขาย ใช้ธุรกรรมเมื่อทำงานกับข้อมูลที่ซับซ้อนที่อาจเสียหายได้จากการอัพเดทพร้อมกัน

กำลังบันทึกข้อมูล

การดำเนินการเขียนฐานข้อมูลพื้นฐานคือชุดที่บันทึกข้อมูลใหม่เป็นการอ้างอิงฐานข้อมูลที่ระบุแทนที่ข้อมูลที่มีอยู่ใด ๆ ที่พา ธ นั้น เพื่อให้เข้าใจชุดเราจะสร้างแอพบล็อกง่ายๆ ข้อมูลสำหรับแอปของคุณถูกเก็บไว้ที่การอ้างอิงฐานข้อมูลนี้:

ชวา
final FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference ref = database.getReference("server/saving-data/fireblog");
Node.js
// Import Admin SDK
var admin = require("firebase-admin");

// Get a database reference to our blog
var db = admin.database();
var ref = db.ref("server/saving-data/fireblog");
หลาม
# Import database module.
from firebase_admin import db

# Get a database reference to our blog.
ref = db.reference('server/saving-data/fireblog')
ไป
// 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")

เริ่มจากการบันทึกข้อมูลผู้ใช้ เราจะจัดเก็บผู้ใช้แต่ละคนด้วยชื่อผู้ใช้ที่ไม่ซ้ำกันและเราจะจัดเก็บชื่อเต็มและวันเกิดของพวกเขา เนื่องจากผู้ใช้แต่ละคนจะมีชื่อผู้ใช้ที่ไม่ซ้ำกันจึงเหมาะสมที่จะใช้วิธีการตั้งค่าที่นี่แทนวิธีการพุชเนื่องจากคุณมีรหัสและไม่จำเป็นต้องสร้าง

ก่อนอื่นให้สร้างการอ้างอิงฐานข้อมูลกับข้อมูลผู้ใช้ของคุณ จากนั้นใช้ set() / setValue() เพื่อบันทึกวัตถุผู้ใช้ไปยังฐานข้อมูลด้วยชื่อผู้ใช้ชื่อเต็มและวันเกิด คุณสามารถผ่านการตั้งค่าสตริง, จำนวน, บูลีน, เป็น null , อาร์เรย์หรือวัตถุ JSON ใด ๆ การผ่าน null จะเป็นการลบข้อมูลในตำแหน่งที่ระบุ ในกรณีนี้คุณจะผ่านวัตถุ:

ชวา
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
var 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"
  }
});
หลาม
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'
    }
})
ไป

// 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)
}

เมื่ออ็อบเจ็กต์ JSON ถูกบันทึกไปยังฐานข้อมูลคุณสมบัติอ็อบเจ็กต์จะถูกแม็พกับตำแหน่งชายด์ของฐานข้อมูลโดยอัตโนมัติในรูปแบบซ้อน ตอนนี้หากคุณนำทางไปยัง URL https://docs-examples.firebaseio.com/server/saving-data/fireblog/users/alanisawesome/full_name เราจะเห็นค่า "Alan Turing" คุณยังสามารถบันทึกข้อมูลไปยังตำแหน่งลูกโดยตรง:

ชวา
usersRef.child("alanisawesome").setValueAsync(new User("June 23, 1912", "Alan Turing"));
usersRef.child("gracehop").setValueAsync(new User("December 9, 1906", "Grace Hopper"));
Node.js
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"
});
หลาม
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'
})
ไป
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)
}

ตัวอย่างสองตัวอย่างข้างต้น - การเขียนค่าทั้งสองในเวลาเดียวกันเป็นวัตถุและเขียนแยกกันไปยังตำแหน่งลูก - จะส่งผลให้ข้อมูลเดียวกันถูกบันทึกไว้ในฐานข้อมูลของคุณ:

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

ตัวอย่างแรกจะทริกเกอร์หนึ่งเหตุการณ์บนไคลเอนต์ที่กำลังดูข้อมูลเท่านั้นในขณะที่ตัวอย่างที่สองจะทริกเกอร์สองเหตุการณ์ เป็นสิ่งสำคัญที่จะต้องทราบว่าหากข้อมูลมีอยู่แล้วที่ usersRef วิธีแรกจะเขียนทับมัน แต่วิธีที่สองจะปรับเปลี่ยนค่าของแต่ละโหนดลูกที่แยกต่างหากในขณะที่ปล่อยให้ลูกอื่น ๆ ของ usersRef ไม่เปลี่ยนแปลง

กำลังอัปเดตข้อมูลที่บันทึกไว้

หากคุณต้องการเขียนไปยังหลาย ๆ ลูกของตำแหน่งฐานข้อมูลในเวลาเดียวกันโดยไม่ต้องเขียนทับโหนดลูกอื่น ๆ คุณสามารถใช้วิธีการอัพเดตดังที่แสดงด้านล่าง:

ชวา
DatabaseReference hopperRef = usersRef.child("gracehop");
Map<String, Object> hopperUpdates = new HashMap<>();
hopperUpdates.put("nickname", "Amazing Grace");

hopperRef.updateChildrenAsync(hopperUpdates);
Node.js
var hopperRef = usersRef.child("gracehop");
hopperRef.update({
  "nickname": "Amazing Grace"
});
หลาม
hopper_ref = users_ref.child('gracehop')
hopper_ref.update({
    'nickname': 'Amazing Grace'
})
ไป
hopperRef := usersRef.Child("gracehop")
if err := hopperRef.Update(ctx, map[string]interface{}{
	"nickname": "Amazing Grace",
}); err != nil {
	log.Fatalln("Error updating child:", err)
}

นี่จะอัปเดตข้อมูลของเกรซเพื่อรวมชื่อเล่นของเธอ หากคุณใช้ชุดที่นี่แทนการอัพเดตมันจะลบทั้ง full_name และ date_of_birth ออกจาก hopperRef ของคุณ

ฐานข้อมูล Firebase Realtime ยังรองรับการอัปเดตหลายเส้นทาง ซึ่งหมายความว่าการอัปเดตสามารถอัปเดตค่าที่หลาย ๆ ตำแหน่งในฐานข้อมูลของคุณได้ในเวลาเดียวกันซึ่งเป็นคุณสมบัติที่มีประสิทธิภาพซึ่งช่วยให้คุณสามารถลดความผิดปกติ ของข้อมูลของคุณ ได้ เมื่อใช้การอัปเดตหลายเส้นทางคุณสามารถเพิ่มชื่อเล่นให้กับทั้ง Grace และ Alan ในเวลาเดียวกัน:

ชวา
Map<String, Object> userUpdates = new HashMap<>();
userUpdates.put("alanisawesome/nickname", "Alan The Machine");
userUpdates.put("gracehop/nickname", "Amazing Grace");

usersRef.updateChildrenAsync(userUpdates);
Node.js
usersRef.update({
  "alanisawesome/nickname": "Alan The Machine",
  "gracehop/nickname": "Amazing Grace"
});
หลาม
users_ref.update({
    'alanisawesome/nickname': 'Alan The Machine',
    'gracehop/nickname': 'Amazing Grace'
})
ไป
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)
}

หลังจากอัพเดตนี้ทั้ง Alan และ Grace ได้เพิ่มชื่อเล่นไว้:

{
  "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"
    }
  }
}

โปรดทราบว่าการพยายามอัปเดตวัตถุโดยการเขียนวัตถุที่มีพา ธ รวมอยู่จะทำให้เกิดพฤติกรรมที่แตกต่างกัน ลองมาดูกันว่าจะเกิดอะไรขึ้นถ้าคุณลองอัปเดต Grace และ Alan ด้วยวิธีนี้:

ชวา
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
usersRef.update({
  "alanisawesome": {
    "nickname": "Alan The Machine"
  },
  "gracehop": {
    "nickname": "Amazing Grace"
  }
});
หลาม
users_ref.update({
    'alanisawesome': {
        'nickname': 'Alan The Machine'
    },
    'gracehop': {
        'nickname': 'Amazing Grace'
    }
})
ไป
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)
}

สิ่งนี้ส่งผลให้เกิดพฤติกรรมที่แตกต่างกันนั่นคือการเขียนทับโหนดทั้งหมด /users

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

การเพิ่มการติดต่อกลับให้เสร็จสมบูรณ์

ใน Node.js และ Java Admin SDKs หากคุณต้องการที่จะรู้ว่าเมื่อใดที่ข้อมูลของคุณได้รับการยืนยันคุณสามารถเพิ่มการติดต่อกลับให้เสร็จสมบูรณ์ได้ ทั้งวิธีการตั้งค่าและการอัปเดตใน SDK เหล่านี้ใช้การเรียกกลับที่เสร็จสมบูรณ์ซึ่งเป็นทางเลือกซึ่งเรียกว่าเมื่อการเขียนถูกส่งไปยังฐานข้อมูล หากการโทรไม่สำเร็จด้วยเหตุผลบางอย่างการติดต่อกลับจะถูกส่งผ่านวัตถุข้อผิดพลาดที่ระบุว่าเหตุใดจึงเกิดความล้มเหลวขึ้น ใน Python และ Go SDK ผู้ดูแลระบบวิธีการเขียนทั้งหมดจะถูกบล็อก นั่นคือวิธีการเขียนจะไม่ส่งคืนจนกว่าการเขียนจะถูกส่งไปยังฐานข้อมูล

ชวา
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", function(error) {
  if (error) {
    alert("Data could not be saved." + error);
  } else {
    alert("Data saved successfully.");
  }
});

การบันทึกรายการข้อมูล

เมื่อสร้างรายการข้อมูลเป็นสิ่งสำคัญที่ต้องคำนึงถึงลักษณะของผู้ใช้หลายคนของแอพพลิเคชั่นส่วนใหญ่และปรับโครงสร้างรายการของคุณตามลำดับ ขยายตัวอย่างข้างต้นลองเพิ่มบทความในบล็อกลงในแอพของคุณ สัญชาตญาณแรกของคุณอาจจะใช้การตั้งค่าเพื่อเก็บเด็กที่มีดัชนีจำนวนเต็มเพิ่มอัตโนมัติเช่นต่อไปนี้:

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

หากผู้ใช้เพิ่มโพสต์ใหม่มันจะถูกเก็บไว้เป็น /posts/2 สิ่งนี้จะใช้ได้หากมีผู้เขียนเพียงคนเดียวเท่านั้นที่เพิ่มโพสต์ แต่ในแอปพลิเคชันบล็อกที่ทำงานร่วมกันของคุณผู้ใช้หลายคนอาจเพิ่มโพสต์ในเวลาเดียวกัน หากผู้เขียนสองคนเขียนไปที่ /posts/2 พร้อมกันดังนั้นอีกหนึ่งโพสต์จะถูกลบโดยผู้อื่น

เพื่อแก้ปัญหานี้ ไคลเอ็นต์ Firebase ได้จัดเตรียมฟังก์ชัน push() ที่สร้าง คีย์ เฉพาะสำหรับเด็กใหม่แต่ละคน โดยใช้คีย์ลูกที่ไม่ซ้ำกันลูกค้าหลายคนสามารถเพิ่มเด็ก ๆ ไปยังสถานที่เดียวกันในเวลาเดียวกันโดยไม่ต้องกังวลเกี่ยวกับความขัดแย้งในการเขียน

ชวา
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
var postsRef = ref.child("posts");

var 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"
});
หลาม
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'
})
ไป

// 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)
}

คีย์ที่ไม่ซ้ำกันจะขึ้นอยู่กับการประทับเวลาดังนั้นรายการจะเรียงลำดับตามลำดับเวลาโดยอัตโนมัติ เนื่องจาก Firebase สร้างคีย์เฉพาะสำหรับแต่ละโพสต์บล็อกจะไม่มีข้อขัดแย้งในการเขียนเกิดขึ้นหากผู้ใช้หลายคนเพิ่มโพสต์ในเวลาเดียวกัน ขณะนี้ข้อมูลฐานข้อมูลของคุณมีลักษณะดังนี้:

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

ใน JavaScript, Python และ Go, รูปแบบของการโทร push() จากนั้นเรียก set() ทันทีนั้นเป็นเรื่องธรรมดาที่ Firebase SDK จะให้คุณรวมพวกเขาโดยส่งผ่านข้อมูลเพื่อตั้งค่าโดยตรงเพื่อ push() ดังนี้:

ชวา
// 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"
});
หลาม
# This is equivalent to the calls to push().set(...) above
posts_ref.push({
    'author': 'gracehop',
    'title': 'Announcing COBOL, a New Programming Language'
})
ไป
if _, err := postsRef.Push(ctx, &Post{
	Author: "gracehop",
	Title:  "Announcing COBOL, a New Programming Language",
}); err != nil {
	log.Fatalln("Error pushing child node:", err)
}

การรับคีย์เฉพาะที่สร้างโดยการกด ()

การเรียก push() จะส่งคืนการอ้างอิงไปยังพา ธ ข้อมูลใหม่ซึ่งคุณสามารถใช้เพื่อรับคีย์หรือตั้งค่าข้อมูล รหัสต่อไปนี้จะส่งผลให้ข้อมูลเช่นเดียวกับตัวอย่างข้างต้น แต่ตอนนี้เราจะสามารถเข้าถึงคีย์เฉพาะที่สร้างขึ้น:

ชวา
// 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()
var newPostRef = postsRef.push();

// Get the unique key generated by push()
var postId = newPostRef.key;
หลาม
# 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
ไป
// 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

อย่างที่คุณเห็นคุณสามารถรับค่าของคีย์เฉพาะจากการอ้างอิง push() คุณ

ในส่วนถัดไปเกี่ยวกับ การดึงข้อมูล เราจะเรียนรู้วิธีอ่านข้อมูลนี้จากฐานข้อมูล Firebase

การบันทึกข้อมูลการทำธุรกรรม

เมื่อทำงานกับข้อมูลที่ซับซ้อนที่อาจเกิดความเสียหายจากการปรับเปลี่ยนที่เกิดขึ้นพร้อมกันเช่นตัวนับที่เพิ่มขึ้น SDK จะให้การ ดำเนินธุรกรรม

ใน Java และ Node.js คุณให้การดำเนินการเรียกกลับสองรายการ: ฟังก์ชันการปรับปรุงและการเรียกกลับที่สมบูรณ์ ใน Python และ Go การทำธุรกรรมกำลังบล็อกและดังนั้นจึงยอมรับฟังก์ชั่นการอัพเดทเท่านั้น

ฟังก์ชั่นอัพเดทใช้สถานะปัจจุบันของข้อมูลเป็นอาร์กิวเมนต์และควรคืนค่าสถานะที่ต้องการใหม่ที่คุณต้องการเขียน ตัวอย่างเช่นหากคุณต้องการเพิ่มจำนวน upvotes ในบล็อกโพสต์เฉพาะคุณจะเขียนธุรกรรมดังนี้:

ชวา
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
var upvotesRef = db.ref("server/saving-data/fireblog/posts/-JRHTHaIs-jNPLXOQivY/upvotes");
upvotesRef.transaction(function (current_value) {
  return (current_value || 0) + 1;
});
หลาม
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')
ไป
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)
}

ตัวอย่างข้างต้นตรวจสอบเพื่อดูว่าตัวนับเป็น null หรือยังไม่ได้เพิ่มเนื่องจากการทำธุรกรรมสามารถเรียกด้วย null หากไม่มีการเขียนค่าเริ่มต้น

หากโค้ดข้างต้นถูกเรียกใช้โดยไม่มีฟังก์ชั่นการทำธุรกรรมและลูกค้าสองรายพยายามเพิ่มขึ้นพร้อมกันพวกเขาทั้งสองจะเขียน 1 เป็นค่าใหม่ส่งผลให้เพิ่มขึ้นหนึ่งครั้งแทนที่จะเป็นสอง

การเชื่อมต่อเครือข่ายและออฟไลน์เขียน

Firebase Node.js และไคลเอนต์ Java รักษาเวอร์ชันภายในของข้อมูลที่ใช้งานอยู่ เมื่อข้อมูลถูกเขียนมันจะถูกเขียนลงในรุ่นท้องถิ่นนี้ก่อน จากนั้นไคลเอ็นต์จะซิงโครไนซ์ข้อมูลนั้นกับฐานข้อมูลและกับไคลเอนต์อื่น ๆ บนพื้นฐานของ 'ความพยายามอย่างดีที่สุด'

เป็นผลให้การเขียนทั้งหมดไปยังฐานข้อมูลจะทริกเกอร์เหตุการณ์ท้องถิ่นทันทีก่อนที่ข้อมูลใด ๆ จะถูกเขียนไปยังฐานข้อมูล ซึ่งหมายความว่าเมื่อคุณเขียนแอปพลิเคชันโดยใช้ Firebase แอปของคุณจะยังคงตอบสนองโดยไม่คำนึงถึงเวลาแฝงของเครือข่ายหรือการเชื่อมต่ออินเทอร์เน็ต

เมื่อการเชื่อมต่อถูกสร้างขึ้นใหม่เราจะได้รับชุดเหตุการณ์ที่เหมาะสมเพื่อให้ลูกค้า "ทัน" กับสถานะเซิร์ฟเวอร์ปัจจุบันโดยไม่ต้องเขียนโค้ดที่กำหนดเองใด ๆ

การรักษาความปลอดภัยข้อมูลของคุณ

Firebase Realtime Database มีภาษาด้านความปลอดภัยที่ให้คุณกำหนดว่าผู้ใช้รายใดที่สามารถอ่านและเขียนการเข้าถึงโหนดต่าง ๆ ของข้อมูลของคุณ คุณสามารถอ่านเพิ่มเติมได้ใน Secure Your Data