I don't understand how to filter the data lists
my db has the following form
{
"numbers": [0, 1, 2, 3, 4, 5],
"models": {
"random_string_key": {
"name": "model_name",
"value": "some_value"
},
"random_string_key-2": {
"name": "Name",
"value": "any value"
}
}
}
- How i can get array from numbers where all values < 3?
- How i can filter models and get array models where value == "some_value"?
I would like to understand what I am doing wrong
let ref = Database.database().reference()
let refNumbers = ref.child("numbers")
refNumbers
.getData(completion: { error, snapshot in
// snapshot.value == [0, 1, 2, 3, 4, 5]
// OK
})
refNumbers
.queryOrderedByValue()
.queryEnding(beforeValue: 2)
.getData(completion: { error, snapshot in
/*
error: Unable to get latest value for query FQuerySpec (path: /numbers, params: {
en = "[MIN_NAME]";
ep = 2;
i = ".value";
}), client offline with no active listeners and no matching disk cache entries
why???
*/
})
let modelsRef = ref.child("models")
modelsRef
.getData(completion: { error, snapshot in
// snapshot.value == NSDictionary
// OK
/*
[
"key": String
"value": NSDictionary
]
*/
})
modelsRef
.queryEqual(toValue: "some_value", childKey: "value")
.getData(completion: { error, snapshot in
/*
error: null
snapshot.value == nil
why???
*/
})
modelsRef
.queryOrdered(byChild: "value")
.queryEqual(toValue: "some_value")
.getData(completion: { error, snapshot in
/*
Unable to get latest value for query FQuerySpec (path: /models, params: {
ep = some_value;
i = value;
sp = some_value;
}), client offline with no active listeners and no matching disk cache entries
why???
*/
})
I tried all the options that I found on the Internet but the result is 0 Either I get all the data from the list and filter it in the app, or I get nothing Is it possible to filter the data upon receipt?
CodePudding user response:
It is a bit difficult to give you a solution to the issues you described above but I can tell you where you're going wrong.
For #1, when you do the below
...
refNumbers
.queryOrderedByValue()
.queryEnding(beforeValue: 2)
.getData(completion: { error, snapshot in
...
})
refNumbers
is not an array of numbers, it is an 'object'. And queryOrderedByValue()
will not work on this 'single object', neither will .queryEnding(beforeValue: 2)
. You either need to do what you're doing, which is to get the entire data, convert to swift native types and filter, or you need to restructure your data on the DB side.
Similarly, in-case of #2, the object modelsRef
is composed of a number of objects with random keys. So, when you perform a .queryEqual(toValue: "some_value", childKey: "value")
operation, it will not find the child-key named 'value'. This child key is actually a child-key for the objects that modelsRef
is composed of.
So, again, either you need to get all this data, type cast to native swift types and then filter, or somehow restructure your data.
So, the answer to your question is essentially either continue what you're doing (get data to the app and filter using native swift API which may present scalability challenges later depending on the amount of data), or, restructure your data.
CodePudding user response:
Example with queryStarting
& queryEnding
As requested, here is what works for me.
Database design
I have an event based app, using Firebase Realtime Database, with one parent node, lets call it events
for now, because the real example is mainly in German.
Under events
there is one child for each event, obviously:
{
"events": {
"-L_nMRK8mzXal47IE54x": {
"endDate": 1568715118,
"lat": 48.4382387,
"lon": 10.0499972044298,
"name": "Exampletown - event",
"city": "Exampletown",
"zip": "12345",
"startDate": 1568325600,
"street": "Street 11"
},
"-L_nMRK8mzXal47IE54y": {
"endDate": 1568715118,
"lat": 49.4382387,
"lon": 10.0499972044298,
"name": "Exampletown - event 2",
"city": "Exampletown",
"zip": "12345",
"startDate": 1568325600,
"street": "Street 12"
},
}
}
Swift 4.2
Inside a method I use the following to query the database for all past events based on the current timestamp:
let ref = Database.database().reference()
let query = ref.child("events").queryOrdered(byChild: "endDate").queryStarting(atValue: diffInterval, childKey: "endDate").queryEnding(atValue: now, childKey: "endDate")
// observe single event is sufficient for my app
query.observeSingleEvent(of: .value) { (snapshot) in
if snapshot.childrenCount > 0 {
for snap in snapshot.children {
// create an object for each of the objects of the snapshot
guard let eventData = self.getEventsFromSnapshot(snap: snap as! DataSnapshot) else {return}
// do something with eventData
}
} else {
// custom logging and return of empty array
}
}