ترجمت واجهة Cloud Translation API‏ هذه الصفحة.
Switch to English

استرجاع البيانات

يغطي هذا المستند أساسيات استرداد بيانات قاعدة البيانات ، وكيفية ترتيب البيانات ، وكيفية إجراء استعلامات بسيطة حول البيانات. يتم تنفيذ استرداد البيانات في Admin SDK بشكل مختلف قليلاً عبر لغات البرمجة المختلفة.

  1. المستمعون غير المتزامنين: يتم استرداد البيانات المخزنة في Firebase Realtime Database عن طريق إرفاق مستمع غير متزامن بمرجع قاعدة بيانات. يتم تشغيل المستمع مرة واحدة للحالة الأولية للبيانات ومرة ​​أخرى في أي وقت تتغير البيانات. قد يتلقى مستمع الأحداث عدة أنواع مختلفة من الأحداث . يتم دعم وضع استرداد البيانات هذا في Java و Node.js و Python Admin SDKs.
  2. يقرأ الحظر: يتم استرداد البيانات المخزنة في Firebase Realtime Database عن طريق استدعاء طريقة حظر على مرجع قاعدة البيانات ، والتي تقوم بإرجاع البيانات المخزنة عند المرجع. كل استدعاء أسلوب عملية في وقت واحد. وهذا يعني أن SDK لا يقوم بتسجيل أي عمليات استدعاء تستمع إلى تحديثات البيانات اللاحقة. هذا النموذج لاسترداد البيانات مدعوم في حزم SDK لـ Python و Go Admin.

ابدء

دعنا نعيد النظر في مثال التدوين من المقالة السابقة لفهم كيفية قراءة البيانات من قاعدة بيانات 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 ، تسمى وظيفة المستمع في أي وقت تتم إضافة بيانات جديدة إلى مرجع قاعدة البيانات الخاصة بك ، ولا تحتاج إلى كتابة أي رمز إضافي لتحقيق ذلك.

في Java و Node.js ، تستقبل وظيفة رد الاتصال DataSnapshot ، وهي لقطة من البيانات. اللقطة هي صورة للبيانات في مرجع قاعدة بيانات معين في نقطة زمنية واحدة. يؤدي استدعاء val() / getValue() في لقطة إلى إرجاع تمثيل كائن خاص بلغة البيانات. في حالة عدم وجود بيانات في موقع المرجع ، تكون قيمة اللقطة null . تُرجع طريقة get() في Python تمثيل Python للبيانات مباشرةً. تقوم وظيفة Get() في Go بإلغاء تنظيم البيانات في بنية بيانات معينة.

لاحظ أننا استخدمنا نوع حدث value في المثال أعلاه ، والذي يقرأ المحتويات الكاملة لمرجع قاعدة بيانات Firebase ، حتى إذا تم تغيير جزء واحد فقط من البيانات. value هي أحد أنواع الأحداث الخمسة المختلفة المدرجة أدناه والتي يمكنك استخدامها لقراءة البيانات من قاعدة البيانات.

قراءة أنواع الأحداث في Java و Node.js

القيمة

يتم استخدام حدث value لقراءة لقطة ثابتة للمحتويات في مسار قاعدة بيانات معين ، حيث كانت موجودة في وقت حدث القراءة. يتم تشغيله مرة واحدة مع البيانات الأولية ومرة ​​أخرى في كل مرة تتغير البيانات. يتم تمرير رد الحدث على لقطة تحتوي على جميع البيانات في هذا الموقع ، بما في ذلك البيانات الفرعية. في مثال الرمز أعلاه ، عرضت value جميع مشاركات المدونة في تطبيقك. في كل مرة تتم فيها إضافة مشاركة مدونة جديدة ، ستعيد وظيفة رد الاتصال جميع المشاركات.

تمت إضافة الطفل

عادةً ما يتم استخدام حدث child_added عند استرداد قائمة بالعناصر من قاعدة البيانات. على عكس value التي تُرجع محتويات الموقع child_added ، يتم تشغيل 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 على التوالي. يمكنك أيضًا الوصول إلى معرف المشاركة السابق من الوسيطة 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 لتسجيل إشعار حول 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 عند العمل مع البيانات 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() لتعيين الحد الأقصى لعدد الأطفال المراد limitToLast() معين. إذا قمت بتعيين الحد من 100، في البداية سوف يحصلون إلا على ما يصل إلى 100 child_added الأحداث. إذا كان لديك أقل من 100 رسالة مخزنة في قاعدة البيانات الخاصة بك ، child_added حدث child_added لكل رسالة. ومع ذلك ، إذا كان لديك أكثر من 100 رسالة ، فلن تتلقى سوى حدثًا child_added لـ 100 من هذه الرسائل. هذه هي أول 100 رسالة مرتبة إذا كنت تستخدم limitToFirst() أو آخر 100 رسالة مرتبة إذا كنت تستخدم limitToLast() . ومع تغير البنود، سوف تتلقى child_added الأحداث للسلع التي تدخل الاستعلام و 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() مع 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 المعجمية:

جافا
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() ، يتم ترتيب البيانات التي تحتوي على المفتاح orderByChild() المحدد على النحو التالي:

  1. يأتي الأطفال null بقيمة null للمفتاح الفرعي المحدد أولاً.
  2. يأتي الأطفال الذين لديهم قيمة false لمفتاح الطفل المحدد بعد ذلك. إذا كان لدى العديد من الأطفال قيمة false ، يتم فرزهم معجمًا حسب المفتاح.
  3. يأتي الأطفال ذوي القيمة true لمفتاح الطفل المحدد بعد ذلك. إذا كان لدى العديد من الأطفال قيمة true ، يتم فرزهم معجمًا حسب المفتاح.
  4. يأتي الأطفال ذو القيمة العددية بعد ذلك ، مصنفين بترتيب تصاعدي. إذا كان للعديد من الأطفال نفس القيمة العددية للعقدة التابعة المحددة ، فسيتم فرزها حسب المفتاح.
  5. تأتي السلاسل بعد الأرقام ، ويتم فرزها معجمًا بترتيب تصاعدي. إذا كان للعديد من الأطفال نفس القيمة للعقدة الفرعية المحددة ، فسيتم ترتيبهم معجمًا حسب المفتاح.
  6. تأتي العناصر في النهاية ، ويتم فرزها معجمًا حسب المفتاح بترتيب تصاعدي.

مفتاح الطلب

عند استخدام orderByKey() لفرز بياناتك ، يتم إرجاع البيانات بترتيب تصاعدي حسب المفتاح على النحو التالي. ضع في اعتبارك أن المفاتيح يمكن أن تكون مجرد سلاسل.

  1. يأتي الأطفال الذين لديهم مفتاح يمكن تحليله كعدد صحيح 32 بت أولاً ، مرتبة ترتيبًا تصاعديًا.
  2. يأتي الأطفال الذين لديهم قيمة سلسلة كمفتاحهم بعد ذلك ، ويتم فرزهم معجمًا بترتيب تصاعدي.

OrderByValue

عند استخدام orderByValue() ، يتم ترتيب الأطفال حسب قيمتها. معايير الترتيب هي نفسها الموجودة في orderByChild() ، باستثناء استخدام قيمة العقدة بدلاً من قيمة مفتاح تابع محدد.