Reading and subscription requests may be refined to select only a subset of the watched data nodes, that is, a subset of their child nodes. Such selections (or constraints) are called queries. For example, it is possible to select only last or first n child nodes of the watched data node, or a range of child nodes with respect to their keys (or names).
The ordering of child nodes with respect to their keys, which is used to find out the last or first n ones or a range of them, is formally defined in the Key Ordering section.
Reading the last or first n elements of a list
In Javascript, the previously presented get()
and
subscribe()
methods take an additional optional parameter of type
Constraint
.
The First() and Last()
constraints make it possible to select respectively the first n or last n children of the watched data node:
// const app = Webcom.App("<your-app>"); // UNCOMMENT if you haven't yet an instance of your app!
const database = app.serverlessDb;
// Reference to our list of contacts
const contactsNode = database.rootNode.relativeNode("contacts");
// Get first 5 elements of the list
contactsNode.get(Webcom.Constraint.First(5)) // a constraint can be passed as parameter
.then(snapshot => {
const first5Contacts = Object.values(snapshot.val());
console.log("The first five contacts are:" , first5Contacts.map(contact => contact.firstName).join(", "));
});
// Subscribe to last 5 elements of the list
contactsNode.subscribe(
Webcom.Event.ValueChange,
Webcom.Callback(snapshot => {
// this callback will be called immediately and also in future, each time one of the 5 last nodes is changed
const last5Contacts = Object.values(snapshot.val());
console.log("The last five contacts are now:" , last5Contacts.map(contact => contact.firstName).join(", "));
}),
Webcom.Constraint.Last(5) // a constraint can be passed as 3rd parameter
);
In Kotlin, the previously presented get()
and
subscribe(...)
methods take an additional optional constraint
parameter of
type Constraint
. The
First
and
Last
subclasses make it possible to
respectively select the first n or last n children of the watched data node:
import com.orange.webcom.sdk.datasync.subscription.Constraint.*
import com.orange.webcom.sdk.datasync.subscription.SubscribableEvent.*
// Reference to our list of contacts
val app = WebcomApplication.default
val manager = app.datasyncService.createManager()
val contactsNode = manager / "contacts"
// Get first 5 elements of the list
contactsNode.get(First(5)) { // a constraint can be passed as parameter
if (it is WebcomResult.Success) { // it: WebcomResult<DatasyncValue>.Success
val first5Contacts = it.result.asListOf(Contact::class)
println("The first five contacts are: ${first5Contacts.map { it.firstName }?.joinToString(", ")}")
}
}
// Subscribe to last 5 elements of the list
val subscription = contactsNode.subscribe(Value.Changed::class, Last(5)) { // a constraint can be passed as 2nd parameter
if (it is Notification.DataNotification) { // it: Notification<Value.Changed>.DataNotification
val last5Contacts = it.data.value.asListOf(Contact::class)
println("The last five contacts are now: ${last5Contacts.map { it.firstName }?.joinToString(", ")}")
}
}
In Swift, the subscribe()
method accepts a DatasyncChildrenConstraint
value in the chidrenConstraint
parameter, which makes it possible to refine the queried data. The
first(limit:)
and last(limit:)
constraint values make it possible to respectively select the first n or last n children of the watched data node:
// Reference to our list of contacts
let manager = Webcom.defaultApplication.datasyncService.createManager()
let contactsNode = manager / "contacts"
// Subscribe to last 5 elements of the list
contactsNode?.subscribe(to: .valueChange, childrenConstraint: .last(limit: 5)) { event in
guard let last5Contacts: [Contact] = event.value.decoded() else {
return
}
print("The last five contacts are now:", last5Contacts.map(\.firstName).joined(separator: ", "))
}
// or:
// Subscribe to first 5 elements of the list
contactsNode?.subscribe(to: .valueChange, childrenConstraint: .first(limit: 5)) { event in
guard let first5Contacts: [Contact] = event.value.decoded() else {
return
}
print("The first five contacts are now:", first5Contacts.map(\.firstName).joined(separator: ", "))
}
Reading a range of keys
Before querying a range of child nodes, please read the Key Ordering section to understand how the keys of child nodes (ie their names) are sorted under a data node.
In JavaScript, the Between()
constraint selects
all children between 2 keys (inclusive).
// const app = Webcom.App("<your-app>"); // UNCOMMENT if you haven't yet an instance of your app!
const database = app.serverlessDb;
// Reference to our list of contacts
const contactsNode = database.rootNode.relativeNode("contacts");
// Subscribe to the elements between "a" and "l" (inclusive)
contactsNode.subscribe(
Webcom.Event.ValueChange,
Webcom.Callback(snapshot => {
const rangeContacts = Object.values(snapshot.val());
console.log("Contacts between 'a' and 'l' are now:", rangeContacts.map(contact => contact.firstName).join(", "))
}),
Webcom.Constraint.Between("a", "l")
);
In Kotlin, the Constraint
class has the
Between
sub-class that queries a range of
child nodes between a lower and an upper keys (inclusive):
import com.orange.webcom.sdk.datasync.subscription.Constraint.*
import com.orange.webcom.sdk.datasync.subscription.SubscribableEvent.*
// Reference to our list of contacts
val app = WebcomApplication.default
val manager = app.datasyncService.createManager()
val contactsNode = manager / "contacts"
// Subscribe to the elements between "a" and "l" (inclusive)
val subscription = contactsNode.subscribe(Value.Changed::class, Between("a", "l")) { // it: Notification<Value.Changed>
if (it is Notification.DataNotification) { // it.data: Value.Changed
val rangeContacts = it.data.value.asListOf(Contact::class)
println("Contacts between 'a' and 'l' are now: ${rangeContacts.map { it.firstName }?.joinToString(", ")}")
}
}
In Swift, the between(startKey:endKey:)
constraint value represents a query of child nodes between a lower and an upper keys (inclusive):
// Reference to our list of contacts
let manager = Webcom.defaultApplication.datasyncService.createManager()
let contactsNode = manager / "contacts"
// Subscribe to the elements between "a" and "l" (inclusive)
contactsNode?.subscribe(to: .valueChange, childrenConstraint: .between(startKey: "a", endKey: "l")) { event in
guard let rangeContacts: [Contact] = event.value.decoded() else {
return
}
print("Contacts between 'a' and 'l' are now:", rangeContacts.map(\.firstName).joined(separator: ", "))
// => jimix
}
Reading from a key with a limit
It is possible to query the n child nodes after or before a given key (child name). Such a query is still computed along the key order definition.
In JavaScript, the StartAt()
and
EndAt()
constraints select either all (no given limit
parameter) or n (passed as the limit
parameter) children respectively starting from or ending at a given key
(inclusive).
// const app = Webcom.App("<your-app>"); // UNCOMMENT if you haven't yet an instance of your app!
const database = app.serverlessDb;
// Reference to our list of contacts
const contactsNode = database.rootNode.relativeNode("contacts");
// Subscribe to the 2 elements from "k"
contactsNode.subscribe(
Webcom.Event.ValueChange,
Webcom.Callback(snapshot => {
const twoFromKContacts = Object.values(snapshot.val());
console.log("The 2 contacts from 'k' are now:", twoFromKContacts.map(contact => contact.firstName).join(", "))
}),
Webcom.Constraint.StartAt("k", 2)
);
In Kotlin, the Constraint
class has the
StartAt
and
EndAt
sub-classes that query either all
(no given limit
property) or n (given as the limit
property) children respectively starting from or ending at
a given key (inclusive).
import com.orange.webcom.sdk.datasync.subscription.Constraint.*
import com.orange.webcom.sdk.datasync.subscription.SubscribableEvent.*
// Reference to our list of contacts
val app = WebcomApplication.default
val manager = app.datasyncService.createManager()
val contactsNode = manager / "contacts"
// Subscribe to the elements between "a" and "l" (inclusive)
val subscription = contactsNode.subscribe(Value.Changed::class, Between("a", "l")) { // it: Notification<Value.Changed>
if (it is Notification.DataNotification) { // it.data: Value.Changed
val twoFromKContacts = it.data.value.asListOf(Contact::class)
println("The 2 contacts from 'k' are now: ${twoFromKContacts.map { it.firstName }?.joinToString(", ")}")
}
}
In Swift, simply use the
startAt(key:limit:)
or endAt(key:limit:)
constraint value.
// Reference to our list of contacts
let manager = Webcom.defaultApplication.datasyncService.createManager()
let contactsNode = manager / "contacts"
// Subscribe to the 2 elements from "k"
contactsNode?.subscribe(to: .valueChange, childrenConstraint: .startAt(key: "k", limit: 2)) { event in
guard let twoFromKContacts: [Contact] = event.value.decoded() else {
return
}
print("The 2 contacts from 'k' are now:", twoFromKContacts.map(\.firstName).joined(separator: ", "))
// => lennon, macca
}