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

การดึงข้อมูล

เอกสารนี้ครอบคลุมพื้นฐานของการดึงข้อมูลฐานข้อมูลวิธีการสั่งซื้อข้อมูลและวิธีการสืบค้นข้อมูลอย่างง่าย การดึงข้อมูลใน SDK ผู้ดูแลระบบมีการใช้งานแตกต่างกันเล็กน้อยในภาษาการเขียนโปรแกรมที่แตกต่างกัน

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

เริ่มต้นใช้งาน

มาทบทวนตัวอย่างบล็อกจากบทความก่อนหน้าเพื่อทำความเข้าใจวิธีอ่านข้อมูลจากฐานข้อมูล Firebase โปรดจำไว้ว่าการโพสต์บล็อกในแอปตัวอย่างจะถูกเก็บไว้ที่ URL ฐานข้อมูล https://docs-examples.firebaseio.com/server/saving-data/fireblog/posts.json หากต้องการอ่านข้อมูลโพสต์ของคุณคุณสามารถทำสิ่งต่อไปนี้:

ชวา
public static class Post {

  public String author;
  public String title;

  public Post(String author, String title) {
    // ...
  }

}

// Get a reference to our posts
final FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference ref = database.getReference("server/saving-data/fireblog/posts");

// Attach a listener to read the data at our posts reference
ref.addValueEventListener(new ValueEventListener() {
  @Override
  public void onDataChange(DataSnapshot dataSnapshot) {
    Post post = dataSnapshot.getValue(Post.class);
    System.out.println(post);
  }

  @Override
  public void onCancelled(DatabaseError databaseError) {
    System.out.println("The read failed: " + databaseError.getCode());
  }
});
Node.js
// Import Admin SDK
var admin = require("firebase-admin");

// Get a database reference to our posts
var db = admin.database();
var ref = db.ref("server/saving-data/fireblog/posts");

// Attach an asynchronous callback to read the data at our posts reference
ref.on("value", function(snapshot) {
  console.log(snapshot.val());
}, function (errorObject) {
  console.log("The read failed: " + errorObject.code);
});
หลาม
# Import database module.
from firebase_admin import db

# Get a database reference to our posts
ref = db.reference('server/saving-data/fireblog/posts')

# Read the data at the posts reference (this is a blocking operation)
print(ref.get())
ไป

// Post is a json-serializable type.
type Post struct {
	Author string `json:"author,omitempty"`
	Title  string `json:"title,omitempty"`
}

// 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 posts
ref := client.NewRef("server/saving-data/fireblog/posts")

// Read the data at the posts reference (this is a blocking operation)
var post Post
if err := ref.Get(ctx, &post); err != nil {
	log.Fatalln("Error reading value:", err)
}

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

ใน Java และ Node.js ฟังก์ชันการโทรกลับได้รับ DataSnapshot ซึ่งเป็นสแน็ปช็อตของข้อมูล สแน็ปช็อตคือรูปภาพของข้อมูลที่มีการอ้างอิงฐานข้อมูลเฉพาะ ณ เวลาหนึ่งจุด Calling val() / getValue() บนสแน็ปช็อตส่งคืนออบเจกต์ที่แสดงภาษาเฉพาะของข้อมูล หากไม่มีข้อมูลอยู่ในตำแหน่งของการอ้างอิงค่าของสแนปชอตจะเป็น null เมธอด get() ใน Python ส่งคืนการแทนค่า Python ของข้อมูลโดยตรง ฟังก์ชั่น Get() ใน Go ลบข้อมูลออกเป็นโครงสร้างข้อมูลที่กำหนด

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

อ่านประเภทเหตุการณ์ใน Java และ Node.js

ความคุ้มค่า

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

เด็กเพิ่ม

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

หากคุณต้องการดึงเฉพาะข้อมูลในแต่ละโพสต์ใหม่ที่เพิ่มลงในแอพบล็อกของคุณคุณสามารถใช้ child_added :

ชวา
ref.addChildEventListener(new ChildEventListener() {
  @Override
  public void onChildAdded(DataSnapshot dataSnapshot, String prevChildKey) {
    Post newPost = dataSnapshot.getValue(Post.class);
    System.out.println("Author: " + newPost.author);
    System.out.println("Title: " + newPost.title);
    System.out.println("Previous Post ID: " + prevChildKey);
  }

  @Override
  public void onChildChanged(DataSnapshot dataSnapshot, String prevChildKey) {}

  @Override
  public void onChildRemoved(DataSnapshot dataSnapshot) {}

  @Override
  public void onChildMoved(DataSnapshot dataSnapshot, String prevChildKey) {}

  @Override
  public void onCancelled(DatabaseError databaseError) {}
});
Node.js
// Retrieve new posts as they are added to our database
ref.on("child_added", function(snapshot, prevChildKey) {
  var newPost = snapshot.val();
  console.log("Author: " + newPost.author);
  console.log("Title: " + newPost.title);
  console.log("Previous Post ID: " + prevChildKey);
});

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

เด็กเปลี่ยนไป

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

คุณสามารถใช้ child_changed เพื่ออ่านข้อมูลที่อัพเดตในบล็อกโพสต์เมื่อมีการแก้ไข:

ชวา
ref.addChildEventListener(new ChildEventListener() {
  @Override
  public void onChildAdded(DataSnapshot dataSnapshot, String prevChildKey) {}

  @Override
  public void onChildChanged(DataSnapshot dataSnapshot, String prevChildKey) {
    Post changedPost = dataSnapshot.getValue(Post.class);
    System.out.println("The updated post title is: " + changedPost.title);
  }

  @Override
  public void onChildRemoved(DataSnapshot dataSnapshot) {}

  @Override
  public void onChildMoved(DataSnapshot dataSnapshot, String prevChildKey) {}

  @Override
  public void onCancelled(DatabaseError databaseError) {}
});
Node.js
// Get the data on a post that has changed
ref.on("child_changed", function(snapshot) {
  var changedPost = snapshot.val();
  console.log("The updated post title is " + changedPost.title);
});

เด็กถูกลบ

เหตุการณ์ child_removed จะถูกทริกเกอร์เมื่อมีการลบเด็กทันที มันมักจะใช้ร่วมกับ child_added และ child_changed สแน็ปช็อตที่ส่งไปยังการเรียกกลับเหตุการณ์มีข้อมูลสำหรับเด็กที่ถูกลบ

ในตัวอย่างบล็อกคุณสามารถใช้ child_removed เพื่อบันทึกการแจ้งเตือนเกี่ยวกับโพสต์ที่ถูกลบไปยังคอนโซล:

ชวา
ref.addChildEventListener(new ChildEventListener() {
  @Override
  public void onChildAdded(DataSnapshot dataSnapshot, String prevChildKey) {}

  @Override
  public void onChildChanged(DataSnapshot dataSnapshot, String prevChildKey) {}

  @Override
  public void onChildRemoved(DataSnapshot dataSnapshot) {
    Post removedPost = dataSnapshot.getValue(Post.class);
    System.out.println("The blog post titled " + removedPost.title + " has been deleted");
  }

  @Override
  public void onChildMoved(DataSnapshot dataSnapshot, String prevChildKey) {}

  @Override
  public void onCancelled(DatabaseError databaseError) {}
});
Node.js
// Get a reference to our posts
var ref = db.ref("server/saving-data/fireblog/posts");

// Get the data on a post that has been removed
ref.on("child_removed", function(snapshot) {
  var deletedPost = snapshot.val();
  console.log("The blog post titled '" + deletedPost.title + "' has been deleted");
});

เด็กย้าย

เหตุการณ์ child_moved ถูกใช้เมื่อทำงานกับข้อมูลที่สั่งซื้อซึ่งครอบคลุมใน ส่วนถัดไป

รับประกันเหตุการณ์

ฐานข้อมูล Firebase รับประกันความสำคัญหลายประการเกี่ยวกับเหตุการณ์:

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

เนื่องจากเหตุการณ์ที่มีคุณค่าจะถูกทริกเกอร์ล่าสุดเสมอตัวอย่างต่อไปนี้จึงจะทำงานได้เสมอ:

ชวา
final AtomicInteger count = new AtomicInteger();

ref.addChildEventListener(new ChildEventListener() {
  @Override
  public void onChildAdded(DataSnapshot dataSnapshot, String prevChildKey) {
    // New child added, increment count
    int newCount = count.incrementAndGet();
    System.out.println("Added " + dataSnapshot.getKey() + ", count is " + newCount);
  }

  // ...
});

// The number of children will always be equal to 'count' since the value of
// the dataSnapshot here will include every child_added event triggered before this point.
ref.addListenerForSingleValueEvent(new ValueEventListener() {
  @Override
  public void onDataChange(DataSnapshot dataSnapshot) {
    long numChildren = dataSnapshot.getChildrenCount();
    System.out.println(count.get() + " == " + numChildren);
  }

  @Override
  public void onCancelled(DatabaseError databaseError) {}
});
Node.js
var count = 0;

ref.on("child_added", function(snap) {
  count++;
  console.log("added:", snap.key);
});

// length will always equal count, since snap.val() will include every child_added event
// triggered before this point
ref.once("value", function(snap) {
  console.log("initial data loaded!", snap.numChildren() === count);
});

กำลังถอนการโทรกลับ

การโทรกลับจะถูกลบออกโดยการระบุประเภทเหตุการณ์และฟังก์ชั่นการโทรกลับที่จะลบออกดังต่อไปนี้:

ชวา
// Create and attach listener
ValueEventListener listener = new ValueEventListener() {
    // ...
};
ref.addValueEventListener(listener);

// Remove listener
ref.removeEventListener(listener);
Node.js
ref.off("value", originalCallback);

หากคุณผ่านบริบทของขอบเขตไปที่ on() จะต้องถูกส่งผ่านเมื่อแยกการโทรกลับ:

ชวา
// Not applicable for Java
Node.js
ref.off("value", originalCallback, this);

หากคุณต้องการลบการโทรกลับทั้งหมดในสถานที่หนึ่งคุณสามารถทำสิ่งต่อไปนี้:

ชวา
// No Java equivalent, listeners must be removed individually.
Node.js
// Remove all value callbacks
ref.off("value");

// Remove all callbacks of any type
ref.off();

อ่านข้อมูลเพียงครั้งเดียว

ในบางกรณีการโทรกลับอาจถูกเรียกใช้ครั้งเดียวแล้วลบออกทันที เราได้สร้างฟังก์ชั่นตัวช่วยเพื่อให้ง่าย:

ชวา
ref.addListenerForSingleValueEvent(new ValueEventListener() {
  @Override
  public void onDataChange(DataSnapshot dataSnapshot) {
    // ...
  }

  @Override
  public void onCancelled(DatabaseError databaseError) {
    // ...
  }
});
Node.js
ref.once("value", function(data) {
  // do some stuff once
});
หลาม
# Import database module.
from firebase_admin import db

# Get a database reference to our posts
ref = db.reference('server/saving-data/fireblog/posts')

# Read the data at the posts reference (this is a blocking operation)
print(ref.get())
ไป
// 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 posts
ref := client.NewRef("server/saving-data/fireblog/posts")

// Read the data at the posts reference (this is a blocking operation)
var post Post
if err := ref.Get(ctx, &post); err != nil {
	log.Fatalln("Error reading value:", err)
}

สอบถามข้อมูล

ด้วยการสืบค้นฐานข้อมูล Firebase คุณสามารถเลือกดึงข้อมูลตามปัจจัยต่าง ๆ ได้ ในการสร้างแบบสอบถามในฐานข้อมูลของคุณคุณเริ่มต้นด้วยการระบุวิธีการจัดเรียงข้อมูลของคุณโดยใช้หนึ่งในฟังก์ชั่นการสั่งซื้อ: orderByChild() , orderByKey() หรือ orderByValue() จากนั้นคุณสามารถรวมสิ่งเหล่านี้กับห้าวิธีอื่น ๆ เพื่อดำเนินการค้นหาที่ซับซ้อน: limitToFirst() , limitToLast() , startAt() , endAt() , และ equalTo()

เนื่องจากพวกเราทุกคนที่ Firebase คิดว่าไดโนเสาร์ค่อนข้างเจ๋งเราจะใช้ตัวอย่างจากฐานข้อมูลตัวอย่างของข้อเท็จจริงเกี่ยวกับไดโนเสาร์เพื่อสาธิตวิธีที่คุณสามารถสืบค้นข้อมูลในฐานข้อมูล Firebase ของคุณ:

{
  "lambeosaurus": {
    "height" : 2.1,
    "length" : 12.5,
    "weight": 5000
  },
  "stegosaurus": {
    "height" : 4,
    "length" : 9,
    "weight" : 2500
  }
}

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

สั่งซื้อโดยใช้รหัสลูกที่ระบุ

คุณสามารถสั่งซื้อโหนดโดยใช้คีย์ลูกทั่วไปโดยส่งผ่านคีย์นั้นไปยัง orderByChild() ตัวอย่างเช่นหากต้องการอ่านไดโนเสาร์ทั้งหมดที่เรียงลำดับตามความสูงคุณสามารถทำสิ่งต่อไปนี้:

ชวา
public static class Dinosaur {

  public int height;
  public int weight;

  public Dinosaur(int height, int weight) {
    // ...
  }

}

final DatabaseReference dinosaursRef = database.getReference("dinosaurs");
dinosaursRef.orderByChild("height").addChildEventListener(new ChildEventListener() {
  @Override
  public void onChildAdded(DataSnapshot dataSnapshot, String prevChildKey) {
    Dinosaur dinosaur = dataSnapshot.getValue(Dinosaur.class);
    System.out.println(dataSnapshot.getKey() + " was " + dinosaur.height + " meters tall.");
  }

  // ...
});
Node.js
var db = firebaseAdmin.database();
var ref = db.ref("dinosaurs");
ref.orderByChild("height").on("child_added", function(snapshot) {
  console.log(snapshot.key + " was " + snapshot.val().height + " meters tall");
});
หลาม
ref = db.reference('dinosaurs')
snapshot = ref.order_by_child('height').get()
for key, val in snapshot.items():
    print('{0} was {1} meters tall'.format(key, val))
ไป

// Dinosaur is a json-serializable type.
type Dinosaur struct {
	Height int `json:"height"`
	Width  int `json:"width"`
}

ref := client.NewRef("dinosaurs")

results, err := ref.OrderByChild("height").GetOrdered(ctx)
if err != nil {
	log.Fatalln("Error querying database:", err)
}
for _, r := range results {
	var d Dinosaur
	if err := r.Unmarshal(&d); err != nil {
		log.Fatalln("Error unmarshaling result:", err)
	}
	fmt.Printf("%s was %d meteres tall", r.Key(), d.Height)
}

โหนดใด ๆ ที่ไม่มีคีย์ย่อยที่เราทำการสืบค้นจะถูกเรียงลำดับด้วยค่า null ซึ่งหมายความว่าโหนดจะมาก่อนในการสั่งซื้อ สำหรับรายละเอียดเกี่ยวกับวิธีการสั่งซื้อข้อมูลให้ดูส่วน วิธีสั่งซื้อข้อมูล

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

{
  "lambeosaurus": {
    "dimensions": {
      "height" : 2.1,
      "length" : 12.5,
      "weight": 5000
    }
  },
  "stegosaurus": {
    "dimensions": {
      "height" : 4,
      "length" : 9,
      "weight" : 2500
    }
  }
}

หากต้องการสอบถามความสูงในขณะนี้คุณสามารถใช้พา ธ เต็มไปยังวัตถุแทนการใช้คีย์เดียว:

ชวา
dinosaursRef.orderByChild("dimensions/height").addChildEventListener(new ChildEventListener() {
  @Override
  public void onChildAdded(DataSnapshot dataSnapshot, String prevChildKey) {
    // ...
  }

  // ...
});
Node.js
var ref = db.ref("dinosaurs");
ref.orderByChild("dimensions/height").on("child_added", function(snapshot) {
  console.log(snapshot.key + " was " + snapshot.val().height + " meters tall");
});
หลาม
ref = db.reference('dinosaurs')
snapshot = ref.order_by_child('dimensions/height').get()
for key, val in snapshot.items():
    print('{0} was {1} meters tall'.format(key, val))
ไป
ref := client.NewRef("dinosaurs")

results, err := ref.OrderByChild("dimensions/height").GetOrdered(ctx)
if err != nil {
	log.Fatalln("Error querying database:", err)
}
for _, r := range results {
	var d Dinosaur
	if err := r.Unmarshal(&d); err != nil {
		log.Fatalln("Error unmarshaling result:", err)
	}
	fmt.Printf("%s was %d meteres tall", r.Key(), d.Height)
}

คำค้นหาสามารถสั่งซื้อได้ครั้งละหนึ่งคีย์เท่านั้น การเรียก orderByChild() หลายครั้งในแบบสอบถามเดียวกันจะเกิดข้อผิดพลาด

สั่งซื้อโดยใช้คีย์

นอกจากนี้คุณยังสามารถสั่งซื้อโหนดด้วยปุ่มของพวกเขาโดยใช้ orderByKey() ตัวอย่างต่อไปนี้อ่านไดโนเสาร์ทั้งหมดตามลำดับตัวอักษร:

ชวา
dinosaursRef.orderByKey().addChildEventListener(new ChildEventListener() {
  @Override
  public void onChildAdded(DataSnapshot dataSnapshot, String prevChildKey) {
    System.out.println(dataSnapshot.getKey());
  }

  // ...
});
Node.js
var ref = db.ref("dinosaurs");
ref.orderByKey().on("child_added", function(snapshot) {
  console.log(snapshot.key);
});
หลาม
ref = db.reference('dinosaurs')
snapshot = ref.order_by_key().get()
print(snapshot)
ไป
ref := client.NewRef("dinosaurs")

results, err := ref.OrderByKey().GetOrdered(ctx)
if err != nil {
	log.Fatalln("Error querying database:", err)
}
snapshot := make([]Dinosaur, len(results))
for i, r := range results {
	var d Dinosaur
	if err := r.Unmarshal(&d); err != nil {
		log.Fatalln("Error unmarshaling result:", err)
	}
	snapshot[i] = d
}
fmt.Println(snapshot)

เรียงตามมูลค่า

คุณสามารถสั่งซื้อโหนดได้ด้วยมูลค่าของปุ่มลูก ๆ ของพวกเขาโดยใช้ orderByValue() สมมติว่าไดโนเสาร์กำลังแข่งขันกีฬาดิโนและคุณกำลังติดตามคะแนนของพวกเขาในรูปแบบต่อไปนี้:

{
  "scores": {
    "bruhathkayosaurus" : 55,
    "lambeosaurus" : 21,
    "linhenykus" : 80,
    "pterodactyl" : 93,
    "stegosaurus" : 5,
    "triceratops" : 22
  }
}

ในการจัดเรียงไดโนเสาร์ด้วยคะแนนของพวกเขาคุณสามารถสร้างแบบสอบถามต่อไปนี้:

ชวา
DatabaseReference scoresRef = database.getReference("scores");
scoresRef.orderByValue().addChildEventListener(new ChildEventListener() {
  @Override
  public void onChildAdded(DataSnapshot dataSnapshot, String prevChildKey) {
    System.out.println("The " + dataSnapshot.getKey() + " score is " + dataSnapshot.getValue());
  }

  // ...
});
Node.js
var scoresRef = db.ref("scores");
scoresRef.orderByValue().on("value", function(snapshot) {
  snapshot.forEach(function(data) {
    console.log("The " + data.key + " dinosaur's score is " + data.val());
  });
});
หลาม
ref = db.reference('scores')
snapshot = ref.order_by_value().get()
for key, val in snapshot.items():
    print('The {0} dinosaur\'s score is {1}'.format(key, val))
ไป
ref := client.NewRef("scores")

results, err := ref.OrderByValue().GetOrdered(ctx)
if err != nil {
	log.Fatalln("Error querying database:", err)
}
for _, r := range results {
	var score int
	if err := r.Unmarshal(&score); err != nil {
		log.Fatalln("Error unmarshaling result:", err)
	}
	fmt.Printf("The %s dinosaur's score is %d\n", r.Key(), score)
}

ดูส่วน วิธีการเรียงลำดับข้อมูล สำหรับคำอธิบายเกี่ยวกับวิธีการเรียงลำดับ null บูลีนสตริงและค่าวัตถุเมื่อใช้ orderByValue()

คำค้นหาที่ซับซ้อน

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

ข้อความค้นหา จำกัด

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

การใช้ฐานข้อมูลข้อเท็จจริงไดโนเสาร์และ orderByChild() คุณสามารถค้นหาไดโนเสาร์ที่หนักที่สุดสองตัว:

ชวา
dinosaursRef.orderByChild("weight").limitToLast(2).addChildEventListener(new ChildEventListener() {
  @Override
  public void onChildAdded(DataSnapshot dataSnapshot, String prevChildKey) {
    System.out.println(dataSnapshot.getKey());
  }

  // ...
});
Node.js
var ref = db.ref("dinosaurs");
ref.orderByChild("weight").limitToLast(2).on("child_added", function(snapshot) {
  console.log(snapshot.key);
});
หลาม
ref = db.reference('dinosaurs')
snapshot = ref.order_by_child('weight').limit_to_last(2).get()
for key in snapshot:
    print(key)
ไป
ref := client.NewRef("dinosaurs")

results, err := ref.OrderByChild("weight").LimitToLast(2).GetOrdered(ctx)
if err != nil {
	log.Fatalln("Error querying database:", err)
}
for _, r := range results {
	fmt.Println(r.Key())
}

การเรียกกลับ child_added นั้นจะถูกเรียกสองครั้งยกเว้นในกรณีที่มีไดโนเสาร์น้อยกว่าสองตัวที่ถูกเก็บไว้ในฐานข้อมูล มันจะถูกไล่ออกสำหรับไดโนเสาร์ตัวใหม่ที่หนักกว่าทุกตัวที่ถูกเพิ่มเข้าไปในฐานข้อมูล ใน Python เคียวรีจะส่งคืน OrderedDict โดยตรงที่มีไดโนเสาร์ที่หนักที่สุดสองตัว

ในทำนองเดียวกันคุณสามารถค้นหาไดโนเสาร์ที่สั้นที่สุดสองตัวโดยใช้ limitToFirst() :

ชวา
dinosaursRef.orderByChild("weight").limitToFirst(2).addChildEventListener(new ChildEventListener() {
  @Override
  public void onChildAdded(DataSnapshot dataSnapshot, String prevChildKey) {
    System.out.println(dataSnapshot.getKey());
  }

  // ...
});
Node.js
var ref = db.ref("dinosaurs");
ref.orderByChild("height").limitToFirst(2).on("child_added", function(snapshot) {
  console.log(snapshot.key);
});
หลาม
ref = db.reference('dinosaurs')
snapshot = ref.order_by_child('height').limit_to_first(2).get()
for key in snapshot:
    print(key)
ไป
ref := client.NewRef("dinosaurs")

results, err := ref.OrderByChild("height").LimitToFirst(2).GetOrdered(ctx)
if err != nil {
	log.Fatalln("Error querying database:", err)
}
for _, r := range results {
	fmt.Println(r.Key())
}

การเรียกกลับ child_added นั้นจะถูกเรียกสองครั้งยกเว้นในกรณีที่มีไดโนเสาร์น้อยกว่าสองตัวที่ถูกเก็บไว้ในฐานข้อมูล มันจะถูกยิงอีกครั้งหากไดโนเสาร์หนึ่งในสองตัวแรกถูกลบออกจากฐานข้อมูลเนื่องจากไดโนเสาร์ตัวใหม่จะสั้นที่สุดเป็นอันดับสอง ใน Python เคียวรีจะส่งคืน OrderedDict โดยตรงที่มีไดโนเสาร์ที่สั้นที่สุด

นอกจากนี้คุณยังสามารถ จำกัด การสืบค้นด้วย orderByValue() หากคุณต้องการสร้างลีดเดอร์บอร์ดที่มีไดโนกีฬาไดโนเสาร์ให้คะแนนสูงสุด 3 อันดับแรกคุณสามารถทำสิ่งต่อไปนี้:

ชวา
scoresRef.orderByValue().limitToFirst(3).addChildEventListener(new ChildEventListener() {
  @Override
  public void onChildAdded(DataSnapshot dataSnapshot, String prevChildKey) {
    System.out.println("The " + dataSnapshot.getKey() + " score is " + dataSnapshot.getValue());
  }

  // ...
});
Node.js
var scoresRef = db.ref("scores");
scoresRef.orderByValue().limitToLast(3).on("value", function(snapshot) {
  snapshot.forEach(function(data) {
    console.log("The " + data.key + " dinosaur's score is " + data.val());
  });
});
หลาม
scores_ref = db.reference('scores')
snapshot = scores_ref.order_by_value().limit_to_last(3).get()
for key, val in snapshot.items():
    print('The {0} dinosaur\'s score is {1}'.format(key, val))
ไป
ref := client.NewRef("scores")

results, err := ref.OrderByValue().LimitToLast(3).GetOrdered(ctx)
if err != nil {
	log.Fatalln("Error querying database:", err)
}
for _, r := range results {
	var score int
	if err := r.Unmarshal(&score); err != nil {
		log.Fatalln("Error unmarshaling result:", err)
	}
	fmt.Printf("The %s dinosaur's score is %d\n", r.Key(), score)
}

ข้อความค้นหาช่วง

การใช้ startAt() , endAt() และ equalTo() ช่วยให้คุณเลือกจุดเริ่มต้นและจุดสิ้นสุดโดยพลการสำหรับการสืบค้นของคุณ ตัวอย่างเช่นหากคุณต้องการค้นหาไดโนเสาร์ทั้งหมดที่มีความสูงอย่างน้อยสามเมตรคุณสามารถรวม orderByChild() และ startAt() :

ชวา
dinosaursRef.orderByChild("height").startAt(3).addChildEventListener(new ChildEventListener() {
  @Override
  public void onChildAdded(DataSnapshot dataSnapshot, String prevChildKey) {
    System.out.println(dataSnapshot.getKey());
  }

  // ...
});
Node.js
  var ref = db.ref("dinosaurs");
  ref.orderByChild("height").startAt(3).on("child_added", function(snapshot) {
    console.log(snapshot.key);
  });
หลาม
ref = db.reference('dinosaurs')
snapshot = ref.order_by_child('height').start_at(3).get()
for key in snapshot:
    print(key)
ไป
ref := client.NewRef("dinosaurs")

results, err := ref.OrderByChild("height").StartAt(3).GetOrdered(ctx)
if err != nil {
	log.Fatalln("Error querying database:", err)
}
for _, r := range results {
	fmt.Println(r.Key())
}

คุณสามารถใช้ endAt() เพื่อค้นหาไดโนเสาร์ทั้งหมดที่มีชื่อมาก่อน Pterodactyl lexicographically:

ชวา
dinosaursRef.orderByKey().endAt("pterodactyl").addChildEventListener(new ChildEventListener() {
  @Override
  public void onChildAdded(DataSnapshot dataSnapshot, String prevChildKey) {
    System.out.println(dataSnapshot.getKey());
  }

  // ...
});
Node.js
var ref = db.ref("dinosaurs");
ref.orderByKey().endAt("pterodactyl").on("child_added", function(snapshot) {
  console.log(snapshot.key);
});
หลาม
ref = db.reference('dinosaurs')
snapshot = ref.order_by_key().end_at('pterodactyl').get()
for key in snapshot:
    print(key)
ไป
ref := client.NewRef("dinosaurs")

results, err := ref.OrderByKey().EndAt("pterodactyl").GetOrdered(ctx)
if err != nil {
	log.Fatalln("Error querying database:", err)
}
for _, r := range results {
	fmt.Println(r.Key())
}

คุณสามารถรวม startAt() และ endAt() เพื่อ จำกัด ทั้งสองด้านของข้อความค้นหาของคุณ ตัวอย่างต่อไปนี้ค้นหาไดโนเสาร์ทั้งหมดที่มีชื่อขึ้นต้นด้วยตัวอักษร "b":

ชวา
dinosaursRef.orderByKey().startAt("b").endAt("b\uf8ff").addChildEventListener(new ChildEventListener() {
  @Override
  public void onChildAdded(DataSnapshot dataSnapshot, String prevChildKey) {
    System.out.println(dataSnapshot.getKey());
  }

  // ...
});
Node.js
var ref = db.ref("dinosaurs");
ref.orderByKey().startAt("b").endAt("b\uf8ff").on("child_added", function(snapshot) {
  console.log(snapshot.key);
});
หลาม
ref = db.reference('dinosaurs')
snapshot = ref.order_by_key().start_at('b').end_at(u'b\uf8ff').get()
for key in snapshot:
    print(key)
ไป
ref := client.NewRef("dinosaurs")

results, err := ref.OrderByKey().StartAt("b").EndAt("b\uf8ff").GetOrdered(ctx)
if err != nil {
	log.Fatalln("Error querying database:", err)
}
for _, r := range results {
	fmt.Println(r.Key())
}

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

ชวา
dinosaursRef.orderByChild("height").equalTo(25).addChildEventListener(new ChildEventListener() {
  @Override
  public void onChildAdded(DataSnapshot dataSnapshot, String prevChildKey) {
    System.out.println(dataSnapshot.getKey());
  }

  // ...
});
Node.js
var ref = db.ref("dinosaurs");
ref.orderByChild("height").equalTo(25).on("child_added", function(snapshot) {
  console.log(snapshot.key);
});
หลาม
ref = db.reference('dinosaurs')
snapshot = ref.order_by_child('height').equal_to(25).get()
for key in snapshot:
    print(key)
ไป
ref := client.NewRef("dinosaurs")

results, err := ref.OrderByChild("height").EqualTo(25).GetOrdered(ctx)
if err != nil {
	log.Fatalln("Error querying database:", err)
}
for _, r := range results {
	fmt.Println(r.Key())
}

ข้อความค้นหาช่วงยังมีประโยชน์เมื่อคุณต้องการแบ่งหน้าข้อมูลของคุณ

วางมันทั้งหมดเข้าด้วยกัน

คุณสามารถรวมเทคนิคเหล่านี้ทั้งหมดเพื่อสร้างแบบสอบถามที่ซับซ้อน ตัวอย่างเช่นคุณสามารถค้นหาชื่อไดโนเสาร์ที่สั้นกว่าสเตโกซอรัส:

ชวา
dinosaursRef.child("stegosaurus").child("height").addValueEventListener(new ValueEventListener() {
  @Override
  public void onDataChange(DataSnapshot stegoHeightSnapshot) {
    Integer favoriteDinoHeight = stegoHeightSnapshot.getValue(Integer.class);
    Query query = dinosaursRef.orderByChild("height").endAt(favoriteDinoHeight).limitToLast(2);
    query.addValueEventListener(new ValueEventListener() {
      @Override
      public void onDataChange(DataSnapshot dataSnapshot) {
        // Data is ordered by increasing height, so we want the first entry
        DataSnapshot firstChild = dataSnapshot.getChildren().iterator().next();
        System.out.println("The dinosaur just shorter than the stegosaurus is: " + firstChild.getKey());
      }

      @Override
      public void onCancelled(DatabaseError databaseError) {
        // ...
      }
    });
  }

  @Override
  public void onCancelled(DatabaseError databaseError) {
    // ...
  }
});
Node.js
var ref = db.ref("dinosaurs");
ref.child("stegosaurus").child("height").on("value", function(stegosaurusHeightSnapshot) {
  var favoriteDinoHeight = stegosaurusHeightSnapshot.val();

  var queryRef = ref.orderByChild("height").endAt(favoriteDinoHeight).limitToLast(2)
  queryRef.on("value", function(querySnapshot) {
    if (querySnapshot.numChildren() === 2) {
      // Data is ordered by increasing height, so we want the first entry
      querySnapshot.forEach(function(dinoSnapshot) {
        console.log("The dinosaur just shorter than the stegasaurus is " + dinoSnapshot.key);

        // Returning true means that we will only loop through the forEach() one time
        return true;
      });
    } else {
      console.log("The stegosaurus is the shortest dino");
    }
  });
});
หลาม
ref = db.reference('dinosaurs')
favotire_dino_height = ref.child('stegosaurus').child('height').get()
query = ref.order_by_child('height').end_at(favotire_dino_height).limit_to_last(2)
snapshot = query.get()
if len(snapshot) == 2:
    # Data is ordered by increasing height, so we want the first entry.
    # Second entry is stegosarus.
    for key in snapshot:
        print('The dinosaur just shorter than the stegosaurus is {0}'.format(key))
        return
else:
    print('The stegosaurus is the shortest dino')
ไป
ref := client.NewRef("dinosaurs")

var favDinoHeight int
if err := ref.Child("stegosaurus").Child("height").Get(ctx, &favDinoHeight); err != nil {
	log.Fatalln("Error querying database:", err)
}

query := ref.OrderByChild("height").EndAt(favDinoHeight).LimitToLast(2)
results, err := query.GetOrdered(ctx)
if err != nil {
	log.Fatalln("Error querying database:", err)
}
if len(results) == 2 {
	// Data is ordered by increasing height, so we want the first entry.
	// Second entry is stegosarus.
	fmt.Printf("The dinosaur just shorter than the stegosaurus is %s\n", results[0].Key())
} else {
	fmt.Println("The stegosaurus is the shortest dino")
}

วิธีสั่งข้อมูล

ส่วนนี้อธิบายถึงวิธีการสั่งซื้อข้อมูลของคุณเมื่อใช้ฟังก์ชันการสั่งซื้อทั้งสี่ฟังก์ชัน

orderByChild

เมื่อใช้ orderByChild() ข้อมูลที่มีรหัสลูกที่ระบุจะได้รับคำสั่งดังนี้

  1. เด็กที่มี null สำหรับรหัสลูกที่ระบุจะมาก่อน
  2. เด็กที่มีค่า false สำหรับคีย์ลูกที่ระบุจะมาถัดไป หากเด็กหลายคนมีค่า false พวกเขาจะถูกจัดเรียง พจนานุกรม ตามคีย์
  3. เด็กที่มีค่า true สำหรับคีย์ลูกที่ระบุจะมาถัดไป หากเด็กหลายคนมีค่า true พวกเขาจะถูกจัดเรียงพจนานุกรมตามคีย์
  4. เด็ก ๆ ที่มีค่าตัวเลขจะมาถัดไปเรียงลำดับจากน้อยไปมาก หากเด็กหลายคนมีค่าตัวเลขที่เหมือนกันสำหรับโหนดลูกที่ระบุพวกเขาจะถูกจัดเรียงตามคีย์
  5. สตริงมาตามตัวเลขและเรียงตามพจนานุกรมตามลำดับจากน้อยไปมาก หากเด็กหลายคนมีค่าเดียวกันสำหรับโหนดชายด์ที่ระบุพวกเขาจะได้รับคำสั่งพจนานุกรมโดยคีย์
  6. วัตถุจะมาเป็นอันดับสุดท้ายและเรียงตามพจนานุกรมโดยเรียงตามลำดับจากน้อยไปมาก

orderByKey

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

  1. เด็กที่มีคีย์ที่สามารถแยกวิเคราะห์เป็นจำนวนเต็ม 32- บิตมาก่อนเรียงลำดับจากน้อยไปมาก
  2. เด็ก ๆ ที่มีค่าสตริงเป็นกุญแจของพวกเขาจะมาเรียงลำดับพจนานุกรมตามลำดับจากน้อยไปหามาก

orderByValue

เมื่อใช้ orderByValue() เด็ก ๆ จะได้รับคำสั่งจากมูลค่าของพวกเขา เกณฑ์การสั่งซื้อเหมือนกับใน orderByChild() ยกเว้นค่าของโหนดจะใช้แทนค่าของคีย์ลูกที่ระบุ