Tutorial: Read data

Serverless DatabaseData Structure Read data

To read data from a [[service]] application database, the main provided method is on(), which works with the following four event types:

Method Description
value This event reads the entire content of a data node.
child_added This event reads only the content of the newly created children of a data node.
child_changed This event reads only the content of the updated children of a data node.
child_removed This event reads only the content of the removed children of a data node.

These four events make it possible to register asynchronous callback functions to read data from the application database. The callback function receives a snapshot of the data of a given node of the application database. A snapshot is a picture of the data at a given time. The val() method on a snapshot returns the JavaScript object representation of the data. If the requested data node is empty (no data), the snapshot value will be null.

Conversely, the off() method, which works with the same four event types, makes it possible to detach or unregister the previously registered callback functions. Callbacks can be removed by specifying the event type of the callback to remove and/or the callback function to remove itself, like the following examples:

// Remove all callbacks associated to the "value" event type
adbk.off("value");

// Remove a specific callback
adbk.off("child_added", myChildAddedCallback);

// Remove all callbacks associated to any event type
adbk.off();
// Remove all callbacks associated to the "value" event type
adbk.off(Query.Event.VALUE);

// Remove a specific callback
adbk.off(Query.Event.CHILD_ADDED, myChildAddedCallback);

// Remove all callbacks associated to any event type
adbk.off();
// Remove all callbacks associated to the "value" event type
adbk.offEventType(.value)

// Remove a specific callback
adbk.offEventType(.childAdded, withCallback: myChildAddedCallback)

// Remove all callbacks associated to any event type
adbk.off()

Reading data using the value event

In our address book example (introduced in the write data section), we could read the data at the "contacts" node using the "value" event type:

var contacts = new Webcom("webcom-addressbook").child("contacts");

// Attach an asynchronous callback to read the "contacts" node
contacts.on("value", function(snapshot) {
  console.log(snapshot.val());
});
Webcom contacts = new Webcom(new WebcomApp("webcom-addressbook")).child("contacts");

// Attach an asynchronous callback to read the "contacts" node
contacts.on(Query.Event.VALUE, new OnQuery() {
  @Override
  public void onComplete(DataSnapshot snapData, @Nullable String prevName) {
    // code to handle current data
    Object value = snapData.value();
  }
  @Override
  public void onCancel(WebcomError error) {
    // event subscription was canceled because of permission reason
  }
  @Override
  public void onError(WebcomError error) {
    // an error occured
  }
});
let contacts : WCWebcom = WCWebcom(url : "[[baseUrl]]/base/webcom-addressbook")!.child("contacts")!
contacts.onEventType(.value, withCallback: { (snapData, prevName) in
            if (snapData != nil){
                // code to handle current data
                let value = snapData?.exportVal()
            } else {
                // an error occured
            }
        }) { (error) in
            if (error != nil){
                // event subscription was canceled because of permission reason
            }
        }

With the value event, the callback function is called with the snapshot of the data node both when the callback is registered (providing the initial content of the node) and then each time the data of the node changes (providing future updates of the content of the node). In our example, the callback function will be initially called with the list of all contacts contained in our address book, and will be called afterwards every time a new contact is added or an existing contact is modified or removed.

Reading data using the child_added event

This function is used to retrieve a list of data from the application database. The « child_added » is launched once for each existing child and then again every time a new child is added to the database. In our example, « child_added » will be returned all contacts in our address book, and every time a new contact is added.

If we wanted to retrieve only the data on each new contact added to our address book, we can use « child_added » like the following example:

var contacts = new Webcom("webcom-addressbook").child("contacts");

// add a contact
contacts.set({
  jimix: {
    birthday: "November 27, 1942",
    firstName: "Jimi",
    lastName: "Hendrix",
    phoneNumber: "045 1234 6541",
    email: "jimix@spaceland.com"
  }
});

// watch new contacts
contacts.on("child_added", function(snapshot, prevChildKey) {
  var newContact = snapshot.val();
  console.log("First name: " + newContact.firstName);
  console.log("Last name: " + newContact.lastName);
  console.log("Previous contact: " + prevChildKey);
});
Webcom contacts = new Webcom(new WebcomApp("webcom-addressbook")).child("contacts");

// add a contact
contacts.set(new HashMap() {
  { put("jimix", new HashMap() {
    { put("birthday", "November 27, 1942"); }
    { put("firstName", "Jimi"); }
    { put("lastName", "Hendrix"); }
    { put("phoneNumber", "045 1234 6541"); }
    { put("email", "jimix@spaceland.com"); }
  });}
});

// watch new contacts
contacts.on(Query.Event.CHILD_ADDED, new OnQuery(){
  @Override
  public void onComplete(DataSnapshot snapData, @Nullable String prevName) {
    // code to handle current data
    Map<String, Object> newContact = (Map) snapData.value();
    Log.i("CHILD_ADDED", "First name: " + newContact.get("firstName"));
    Log.i("CHILD_ADDED", "Last name: " + newContact.get("lastName"));
    Log.i("CHILD_ADDED", "Previous contact: " + prevName);
  }
  @Override
  public void onCancel(WebcomError error) {
    // event subscription was canceled because of permission reason
  }
  @Override
  public void onError(WebcomError error) {
    // an error occured
  }
});
let contacts : WCWebcom = WCWebcom(url : "[[baseUrl]]/base/webcom-addressbook")!.child("contacts")!

// add a contact
contacts.set([ "jimix" : [
  "birthday" : "November 27, 1942",
  "firstName" : "Jimi",
  "lastName" : "Hendrix",
  "phoneNumber" : "045 1234 6541",
  "email" : "jimix@spaceland.com"
  ] 
   as NSObject)

// watch new contacts
contacts.onEventType(.childAdded, withCallback: { (snapData, prevName) in
  if (snapData != nil){
        // code to handle current data
        let value = snapData?.exportVal() as! [String : Any]
        print(value["lastName"] as! String)
        print(value["email"] as! String)
  } else {
        // an error occured
  }
}) { (error) in
     if (error != nil){
                // event subscription was canceled because of permission reason
          }
      }

In our example the snapshot contain a contact object. We can access to all properties of this object by calling them directly. We could also access to the previous contact with the argument prevChildKey.

Reading data using the child_changed event

This function is used to retrieve changes on a list of data from the application database. The « child_changed » event is launched when a child node is modified (including all children sub-nodes). For example, in our address book we could use this method to read updated contacts like this:

var contacts = new Webcom("webcom-addressbook").child("contacts");

// update some contact details
contacts.child("macca").update({
    "address": "London 2358644689"
});

// watch updated contacts
contacts.on("child_changed", function(snapshot) {
  var changedContact = snapshot.val();
  console.log("The contact '" + changedContact.firstName + changedContact.lastName + "'was updated");
  console.log("Address: " + changedContact.address);
});
Webcom contacts = new Webcom(new WebcomApp("webcom-addressbook")).child("contacts");

// update some contact details
contacts.child("macca").update(new HashMap() {
  { put("address", "London 2358644689"); }
});

// watch updated contacts
contacts.on(Query.Event.CHILD_CHANGED, new OnQuery(){
  @Override
  public void onComplete(DataSnapshot snapData, @Nullable String prevName) {
    // code to handle current data
    Map<String, Object> changedContact = (Map) snapData.value();
    Log.i("CHILD_CHANGED", String.format("The contact '%s %s' was updated.", changedContact.get("firstName"), changedContact.get("lastName")));
    Log.i("CHILD_ADDED", "Address: " + changedContact.get("address");
  }
  @Override
  public void onCancel(WebcomError error) {
    // event subscription was canceled because of permission reason
  }
  @Override
  public void onError(WebcomError error) {
    // an error occured
  }
});
let contacts : WCWebcom = WCWebcom(url : "[[baseUrl]]/base/webcom-addressbook")!.child("contacts")!

// update some contact details
contacts.child("macca")?.update(["address" : "London 2358644689"] as NSObject)

// watch updated contacts
contacts.onEventType(.childChanged, withCallback: { (snapshot, str) in

    if (snapshot != nil){
       var changedContact = snapshot?.exportVal() as! [String : Any]
       print("The contact : \(changedContact["firstName"] as! String) \(changedContact["lastName"] as! String)  was updated")
       print("Adress : \(changedContact["address"] as! String)")         
     }

})

Reading data using the child_removed event

This function is used to retrieve deleted or removed data from the application database. The « child_removed » event is launched immediately when a child is removed (including all children sub-nodes). For example, in our address book we could use this method to read deleted contacts like this:

var contacts = new Webcom("webcom-addressbook").child("contacts");

// delete a contact
contacts.child("macca").remove();

// watch deleted contacts
contacts.on("child_removed", function(snapshot) {
  var deletedContact = snapshot.val();
  console.log("The following contact '" + deletedContact.lastName + "' has been deleted");
});
Webcom contacts = new Webcom(new WebcomApp("webcom-addressbook")).child("contacts");

// delete a contact
contacts.child("macca").remove();

// watch deleted contacts
contacts.on(Query.Event.CHILD_REMOVED, new OnQuery(){
  @Override
  public void onComplete(DataSnapshot snapData, @Nullable String prevName) {
    // code to handle current data
    Map<String, Object> deletedContact = (Map) snapData.value();
    Log.i("CHILD_CHANGED", String.format("The following contact '%s %s' has been deleted.", deletedContact.get("firstName"), deletedContact.get("lastName")));
  }
  @Override
  public void onCancel(WebcomError error) {
    // event subscription was canceled because of permission reason
  }
  @Override
  public void onError(WebcomError error) {
    // an error occured
  }
});
let contacts : WCWebcom = WCWebcom(url : "[[baseUrl]]/base/webcom-addressbook")!.child("contacts")!

// delete a contact
contacts.child("macca")?.remove()

// watch deleted contacts
contacts.onEventType(.childRemoved,  withCallback: { (snapData, prevName) in
            if (snapData != nil){
                // code to handle current data
                let deletedContact = snapData?.exportVal() as! [String:Any]
                print(" The following contact \(deletedContact["firstName"] as! String) has been deleted ")
            } else {
                // an error occured
            }
        }) { (error) in
            if (error != nil){
                // event subscription was canceled because of permission reason
            }
        }

Reading the last or first n elements of a list

It is possible to add filter when you subscribe to a node and only keep a view of last (or first) n elements for example. Key order definition

// reference to a list of messages
var ref = new Webcom("webcom-chat").child("messagelist");

// subscribe to last 5 elements of the list
ref.limit(5).on("value", function(snapshot) {
  var last5Messages = snapshot.val();
  console.log("The last five messages are" , last5Messages);
});

// or:

// subscribe to first 5 elements of the list
ref.startAt().limit(5).on("value", function(snapshot) {
  var first5Messages = snapshot.val();
  console.log("The first five messages are" , first5Messages);
});
// Available soon
// Available soon

Reading a range of keys

endAt and startAt can be used to query a range of keys. Key order definition

var ref = new Webcom("directory").child("names");

ref.set({"a":"va","b":"vb","c":"vc","d":"vd"})

// subscribe to names between keys "b" and "c"
ref.startAt("b").endAt("c").once("value", function(snapshot) {
  console.log("entries from b to c are" , snapshot.val());
  // =>  {"b":"vb","c":"vc"}
});
// Available soon
// Available soon

Reading from a key name with a limit

It is for example possible to query the 5 first names in a directory starting at a value. Key order definition

var ref = new Webcom("directory").child("names");

ref.set({"a":"va","b":"vb","c":"vc","d":"vd"})

// subscribe to 2 first names starting at keys "b"
ref.startAt("b").limit(2).once("value", function(snapshot) {
  console.log("entries are" , snapshot.val());
  // =>  {"b":"vb","c":"vc"}
});
// Available soon
// Available soon