Catch up on everything we announced at this year's Firebase Summit. Learn more

Veri Kaydetme

Bu belge, Firebase Gerçek Zamanlı Veritabanınıza veri yazmak için dört yöntemi kapsar: ayarlama, güncelleme, gönderme ve işlem desteği.

Veri Kaydetmenin Yolları

Ayarlamak Yaz ya da benzeri bir tanımlanmış yola verileri değiştirmek messages/users/<username>
Güncelleme Tüm verileri değiştirmeden tanımlanmış bir yol için bazı anahtarları güncelleyin
itmek Veritabanındaki verilerin bir listeye ekleyin. Bir listeye yeni bir düğüm itmek her zaman, veritabanı gibi benzersiz bir anahtar oluşturur messages/users/<unique-user-id>/<username>
işlem Eşzamanlı güncellemeler tarafından bozulabilecek karmaşık verilerle çalışırken işlemleri kullanın

Veri Kaydetme

Temel veritabanı yazma işlemi, yeni verileri belirtilen veritabanı referansına kaydeden ve bu yoldaki mevcut verilerin yerini alan bir kümedir. Seti anlamak için basit bir blog uygulaması oluşturacağız. Uygulamanızın verileri şu veritabanı referansında saklanır:

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');
piton
# Import database module.
from firebase_admin import db

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

Bazı kullanıcı verilerini kaydederek başlayalım. Her kullanıcıyı benzersiz bir kullanıcı adıyla saklayacağız ve ayrıca tam adını ve doğum tarihini de saklayacağız. Her kullanıcının benzersiz bir kullanıcı adı olacağından, zaten anahtara sahip olduğunuz ve bir tane oluşturmanız gerekmediğinden, burada Push yöntemi yerine set yöntemini kullanmak mantıklıdır.

İlk olarak, kullanıcı verilerinize bir veritabanı referansı oluşturun. Ardından kullanım set() / setValue() kullanıcıya ait kullanıcı tam adı ve doğum ile veritabanına bir kullanıcı nesneyi kaydedin. Bir dize, sayı, boolean, set geçirebiliriz null , dizi veya herhangi JSON nesnesi. Geçme null belirtilen yerde veriler kaldırılır. Bu durumda ona bir nesne ileteceksiniz:

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'
  }
});
piton
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'
    }
})
Gitmek

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

Bir JSON nesnesi veritabanına kaydedildiğinde, nesne özellikleri otomatik olarak veritabanı alt konumlarına iç içe geçmiş bir şekilde eşlenir. Eğer URL'ye Şimdi eğer https://docs-examples.firebaseio.com/server/saving-data/fireblog/users/alanisawesome/full_name , biz değer "Alan Turing'in" göreceksiniz. Ayrıca verileri doğrudan bir alt konuma da kaydedebilirsiniz:

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'
});
piton
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'
})
Gitmek
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)
}

Yukarıdaki iki örnek - her iki değeri aynı anda bir nesne olarak yazmak ve bunları alt konumlara ayrı ayrı yazmak - aynı verilerin veritabanınıza kaydedilmesine neden olacaktır:

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

İlk örnek, verileri izleyen istemcilerde yalnızca bir olayı tetiklerken, ikinci örnek iki olayı tetikleyecektir. Veriler zaten var olan eğer o notta önemlidir usersRef , birinci yaklaşım üzerine yazmak, ancak diğer çocukları bırakarak ikinci yöntem yalnızca her bir ayrı çocuk düğümün değerini değiştirmek istiyorum usersRef değişmeden.

Kaydedilen Verileri Güncelleme

Bir veritabanı konumunun birden çok alt öğesine aynı anda diğer alt düğümlerin üzerine yazmadan yazmak istiyorsanız, aşağıda gösterildiği gibi güncelleme yöntemini kullanabilirsiniz:

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'
});
piton
hopper_ref = users_ref.child('gracehop')
hopper_ref.update({
    'nickname': 'Amazing Grace'
})
Gitmek
hopperRef := usersRef.Child("gracehop")
if err := hopperRef.Update(ctx, map[string]interface{}{
	"nickname": "Amazing Grace",
}); err != nil {
	log.Fatalln("Error updating child:", err)
}

Bu, Grace'in verilerini takma adını içerecek şekilde güncelleyecektir. Yerine güncelleme burada setini kullanmış olsaydık, her iki silinmiş olurdu full_name ve date_of_birth senin dan hopperRef .

Firebase Realtime Database, çok yollu güncellemeleri de destekler. Güncelleştirme artık aynı anda veritabanında birden fazla yerde değerlerini güncelleyebildiğinizi Bu araçlar, olanak sağlayan güçlü bir özellik olur verilerinizi denormalize . Çok yollu güncellemeleri kullanarak hem Grace'e hem de Alan'a aynı anda takma adlar ekleyebilirsiniz:

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'
});
piton
users_ref.update({
    'alanisawesome/nickname': 'Alan The Machine',
    'gracehop/nickname': 'Amazing Grace'
})
Gitmek
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)
}

Bu güncellemeden sonra Alan ve Grace'in takma adları eklendi:

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

Dahil edilen yollarla nesneler yazarak nesneleri güncellemeye çalışmanın farklı davranışlarla sonuçlanacağını unutmayın. Bunun yerine Grace ve Alan'ı şu şekilde güncellemeye çalışırsanız ne olduğuna bir göz atalım:

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'
  }
});
piton
users_ref.update({
    'alanisawesome': {
        'nickname': 'Alan The Machine'
    },
    'gracehop': {
        'nickname': 'Amazing Grace'
    }
})
Gitmek
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)
}

Yani bütününü üzerine yazarak farklı davranış, bu sonuçlar /users düğüm:

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

Tamamlama Geri Araması Ekleme

Node.js ve Java Admin SDK'larında, verilerinizin ne zaman teslim edildiğini öğrenmek istiyorsanız, bir tamamlama geri araması ekleyebilirsiniz. Bu SDK'lardaki hem ayarlama hem de güncelleme yöntemleri, yazma işlemi veritabanına yapıldığında çağrılan isteğe bağlı bir tamamlama geri araması alır. Arama herhangi bir nedenle başarısız olursa, geri arama, hatanın neden oluştuğunu belirten bir hata nesnesi iletilir. Python ve Go Admin SDK'larında tüm yazma yöntemleri engelliyor. Diğer bir deyişle, yazma yöntemleri, yazma işlemleri veritabanına taahhüt edilene kadar geri dönmez.

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.');
  }
});

Veri Listelerini Kaydetme

Veri listeleri oluştururken, çoğu uygulamanın çok kullanıcılı yapısını akılda tutmak ve liste yapınızı buna göre ayarlamak önemlidir. Yukarıdaki örneği genişleterek, uygulamanıza blog gönderileri ekleyelim. İlk içgüdünüz, aşağıdaki gibi otomatik artan tamsayı dizinleri olan çocukları saklamak için set kullanmak olabilir:

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

Bir kullanıcı yeni yazı ekler Eğer gibi saklanır, /posts/2 . Bu, yalnızca tek bir yazar gönderi ekliyorsa işe yarar, ancak ortak blog uygulamanızda birçok kullanıcı aynı anda gönderi ekleyebilir. İki yazar yazarsan /posts/2 aynı anda, mesajların sonra bir diğeri tarafından silinir.

Bu sorunu çözmek için Firebase istemcileri sağlamak push() her yeni çocuk için benzersiz bir anahtar oluşturur işlevi. Benzersiz alt anahtarlar kullanarak, birkaç istemci, yazma çakışmalarından endişe duymadan, aynı anda aynı konuma çocukları ekleyebilir.

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'
});
piton
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'
})
Gitmek

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

Benzersiz anahtar bir zaman damgasına dayanır, bu nedenle liste öğeleri otomatik olarak kronolojik olarak sıralanır. Firebase, her blog gönderisi için benzersiz bir anahtar oluşturduğundan, birden fazla kullanıcı aynı anda gönderi eklerse yazma çakışmaları oluşmaz. Veritabanı verileriniz şimdi şöyle görünür:

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

JavaScript, Python ve Go, çağıran desende push() ve ardından hemen çağıran set() Firebase SDK verileri geçirerek bunları birleştirmek doğrudan ayarlanmasına olanak tanır, böylece yaygındır push() şöyle:

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'
});;
piton
# This is equivalent to the calls to push().set(...) above
posts_ref.push({
    'author': 'gracehop',
    'title': 'Announcing COBOL, a New Programming Language'
})
Gitmek
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() tarafından oluşturulan benzersiz anahtarı alma

Arayan push() buna anahtarı veya ayar verileri almak için kullanabileceğiniz yeni veri yoluna, bir başvuru döndürür. Aşağıdaki kod, yukarıdaki örnekle aynı verilerle sonuçlanacaktır, ancak şimdi oluşturulan benzersiz anahtara erişimimiz olacak:

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;
piton
# 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
Gitmek
// 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

Gördüğünüz gibi, kendi benzersiz anahtarı değerini alabilirsiniz push() referans.

Sonraki bölümde veri alınıyor , bir Firebase veritabanından bu verileri okumayı öğreneceksiniz.

İşlem Verilerini Kaydetme

Böyle sayıcı olarak eşzamanlı modifikasyonlar tarafından bozulmuş olabilir karmaşık verilerle çalışırken, SDK sağlar işlem operasyonu .

Java ve Node.js'de, işlem işlemine iki geri arama verirsiniz: bir güncelleme işlevi ve isteğe bağlı bir tamamlama geri araması. Python ve Go'da işlem işlemi engelliyor ve bu nedenle yalnızca güncelleme işlevini kabul ediyor.

Güncelleme işlevi, verilerin mevcut durumunu bir argüman olarak alır ve yazmak istediğiniz yeni istenen durumu döndürmelidir. Örneğin, belirli bir blog gönderisindeki olumlu oyların sayısını artırmak isterseniz, aşağıdaki gibi bir işlem yazarsınız:

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;
});
piton
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')
Gitmek
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)
}

Sayaç ise yukarıdaki örnek denetler null veya henüz artırılır edilmemiştir işlemler ile çağrılabilir beri, null varsayılan değer yazılmıştır eğer.

Yukarıdaki kod bir işlem fonksiyonu olmadan çalıştırmak olmuştu ve iki müşteri aynı anda bir artıracaktır teşebbüs ederse, ikisi de yazma ediyorum 1 tek artım iki yerine yeni bir değer olarak ortaya çıkan.

Ağ Bağlantısı ve Çevrimdışı Yazmalar

Firebase Node.js ve Java istemcileri, tüm etkin verilerin kendi dahili sürümlerini korur. Veriler yazıldığında önce bu yerel sürüme yazılır. İstemci daha sonra bu verileri veritabanıyla ve diğer istemcilerle 'en iyi çaba' temelinde senkronize eder.

Sonuç olarak, veritabanına yapılan tüm yazma işlemleri, herhangi bir veri veritabanına yazılmadan hemen önce yerel olayları tetikleyecektir. Eğer Firebase kullanarak uygulama yazdığınızda, uygulama ağ gecikmesi veya Internet bağlantısı ne olursa olsun duyarlı kalacağını Bu araçlar.

Bağlantı yeniden kurulduğunda, istemcinin herhangi bir özel kod yazmak zorunda kalmadan mevcut sunucu durumunu "yakalaması" için uygun olay kümesini alacağız.

Verilerinizin Güvenliğini Sağlama

Firebase Realtime Database, hangi kullanıcıların verilerinizin farklı düğümlerine okuma ve yazma erişimi olduğunu tanımlamanıza olanak tanıyan bir güvenlik diline sahiptir. Sen bu konuda daha fazla bilgi bulabilirsiniz Verilerinizi Güvenli .