Firebase iOS query not ordering as expected - ios

I have saved my data using childByAutoId so that it is ordered chronologically in Firebase. When I query using the query below, and then I print the snapshot.value it prints in the orders as I expected --ordered chronologically--, but when I try to enumerate over snapshot.value, and when I try to get the keys with [snap.value allkeys], they are no longer ordered chronologically. I have tried using [self.refMyOrder queryOrderedByKey] and [self.refMyOrders queryOrderedByChild:#"timestamp" for which I have a child timestamp that is a data-type long of the Epoch time. But still, it is not maintaining the desired order.
I understand that the underlying data structure of an NSDictionary is not an ordered data structure.
What am I doing wrong?
[self.refMyOrders observeSingleEventOfType:FEventTypeValue withBlock:^(FDataSnapshot *snapshot) {
NSLog(#"snapshot.value = %#", snapshot.value);
NSLog(#"all keys = %#", [snapshot.value allKeys]);
}];

So, I read the FDataSnapshot.h header file that comes with the Firebase iOS SDK, and found a way to enumerate over the snapshot so that it remains in the proper order.
[self.refMyOrders observeSingleEventOfType:FEventTypeValue withBlock:^(FDataSnapshot *snapshot) {
for (FDataSnapshot* child in snapshot.children) {
NSLog(#"%# -> %#", child.value[#"orderID"], child.value[#"timestamp"]);
}
}];
This is exactly what I was looking for. I will leave this question here for future users. I couldn't find anything this simple.

Related

How to get chronologically latest post from Firebase?

I am working on app in which Facebook like news feed is used,and i am using Firebase as a database. Everything is working fine, I just need to fetch posts, time wise.
FIRDatabaseQuery * query = [[[_firebaseReference child:#"Demo"]child:#"posts"]queryLimitedToFirst:100];
[query observeSingleEventOfType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot * _Nonnull snapshot) {
if (snapshot.exists) {
postsDictionary = snapshot.value;
[self createSocialAppDataSource];
}
}];
The data in postsDictionary is same as in Database,But i want that data (post) to get sorted respect to time,So how to use query?
structure of my post in database as follow
Thanks
To filter the nodes on a child property, call queryOrderedByChild.
Then when you execute the query against the Firebase Database, there will potentially be multiple results. So the snapshot contains a list of those results. Even if there is only a single result, the snapshot will contain a list of one result.
So you'll need to loop over the children:
FIRDatabaseQuery * query = [[[[_firebaseReference child:#"Demo"] child:#"posts"] queryOrderedByChild: "dateTime"] queryLimitedToFirst:100];
[query observeSingleEventOfType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot * _Nonnull snapshot) {
for ( FDataSnapshot *child in snapshot.children) {
NSLog(#"child.key = %#",child.key);
}
}];
Loosely based on my answer here: IOS Firebase: Loop all key in snapshot.value get messy position
Usually people append the array they are feeding into the collectionView or tableView (for example) but in your case you can [myMutableArray insertObject:myObject atIndex:0]; now when you enumerate through your snapshot each post will be added to the front of your array

how to get the unique key that was created adding a child in firebase?

I am using firebase database for my ios project.
I added some fields using childByAutoId.
[[[_ref child:#"Users"] childByAutoId] setValue:#{#"data": #"my new json data string By aqeel", #"email": #"abc.xyz#email.com"}];
Now for some reason I have to search a specific child from database, say an email id. If email id exists I want to get that unique key of that child.
I am doing this
[[[[_ref child:#"Users"] queryOrderedByChild: #"email" ] queryEqualToValue:#"abc.xyz#email.com" ] observeEventType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot *snapshot) {
NSLog(#"%# Key %# Value", snapshot.key,snapshot.value);
}];
Here in key I get "Users" and in value I get all the entries inUsers field. But I want to get the key for the child abc.xyz#email.com.
Can someone provide me a sample code?
When you execute a query against the Firebase Database, there will potentially be multiple results. So the snapshot contains a list of those results. Even if there is only a single result, the snapshot will contain a list of one result.
This means that you will have to loop over the snapshot.children.
Alternatively you can listen for a single .ChildAdded event and get the child that way:
[[[[_ref child:#"Users"]
queryOrderedByChild: #"email" ]
queryEqualToValue:#"abc.xyz#email.com" ]
observeSingleEventOfType:FIRDataEventTypeChildAdded withBlock:^(FIRDataSnapshot *snapshot) {
NSLog(#"%# Key %# Value", snapshot.key,snapshot.value);
}];

How to retrieve an specific child in Firebase?

The childByAutoId would be useful if you want to save in a node multiple children of the same type, that way each children will have its own unique identifier.
pet:{
KJHBJJHB:{
name:fluffy,
owner:John Smith,
},
KhBHJBJjJ:{
name:fluffy,
owner:Jane Foster,
}
}
Therefore, once I have that uID, and I want to retrieve an specific user using the his/her uID. How do I tell Firebase that I want that specific user? Because I create it and store it in Firebase, but then to read it, don't I need to know the value of the uID? Where do I get it from?
What function do I use to retrieve for example the second user using the uID?
Thanks in advance..
in the title u ask how to get rid so:: get the new ref's key property to get the aid created
FIRDatabaseReference *ref = parent.childByAutoID
NSString *uid = ref.key
BUT thats not what you want id say, so:
to filter out all children where owner = XY which you want I think:
FIRDatabaseReference *ref = your pets node
FIRDatabaseQuery *allPets = [ref queryOrderedByChild:#"owner"];
FIRDatabaseQuery *specificPet = [allPets queryEqualToValue:#"XY"];
[specificPet observeEventType:FEventTypeChildAdded withBlock:^(FIRDataSnapshot *snapshot) {
NSDictionary *dict = snapshot.value;
NSString *key = snapshot.key;
NSLog(#"key = %# for child %#", key, dict);
}];
see: Query users by name or email address using Firebase (Swift)

Trouble with a Firebase Query

I am new to firebase because parse is shutting down and I have spent days trying to figure out how to find the parent of the child I am trying to query. For example let's say my parent is email and my child is person1. Now in my dictionary person1 is paired with person 1(there is a complicated reason why I am doing this but it is not a problem)
So my code looks like this.
Firebase *fb=[[Firebase alloc]initWithUrl:#"https:firebaseURL"];
[[[fb queryOrderedByChild:#"person1 string"] queryEqualToValue:#"person1 string"]
observeEventType:FEventTypeChildAdded withBlock:^(FDataSnapshot *snapshot) {
NSLog(#"888888%#", snapshot.key);
}];
NOTHING SHOWS
I really would appreciate the help. So basically I need to know how to query based on the child value and find the parent to that child. Thanks everyone.
A couple of things;
Your query is malformed. Ordered by defines what 'field' or node name you want to search.. it's the KEY part of the KEY:VALUE pair.
[fb queryOrderedByChild:#"person1 string"] should be
[fb queryOrderedByChild:#"node name to search"]
Let me break it down
Given
users
uid_0
name: "Jay"
state: "Florida"
uid_1
name: "Leroy"
state: "Colorado"
and code
// a reference to the parent node we want to query
Firebase *usersRef = [self.myRootRef childByAppendingPath:#"users"];
//define which child node name we want to search
FQuery *statesRef = [usersRef queryOrderedByChild:#"state"];
//define the value we want to search for
FQuery *specificStateRef = [statesRef queryEqualToValue:#"Florida"];
[specificStateRef observeEventType:FEventTypeChildAdded withBlock:^(FDataSnapshot *snapshot) {
NSLog(#"snapshot: %#", snapshot);
}];
snapshot will contain
uid_0
name: "Jay"
state: "Florida"
The parent node name is uid_0 and can be retrieved with
NSLog(#" key: %#", snapshot.key);
and the name and state are key value pairs stored in the value
NSLog(#" value: %#", snapshot.value);

Using predicates to filter out sources when doing a query

I'm trying to make an HKStatisticsQuery on step count, with a predicate that dismisses user-entered values.
I found out there were 2 differences between user-entered values and passively-logged values:
Source:
-passively logged values have "A's iPhone" for the source
-user-entered values have "Health" for the source
'Was User Entered' metadata key:
-passively logged don't have the metadata key at all
-user-entered values have a 'Was User Entered' metadata key set to true
I've tried this predicate, in an attempt to only get data that had 'Was User Entered' set to false:
HKQuery.predicateForObjectsWithMetadataKey(HKMetadataKeyWasUserEntered, allowedValues: [false])
I got no results, and someone helped me realize that the metadata key doesn't even exist if it's passively logged (kind of redundant...)
Given the above differences, does anyone know of any other way to extract passively-logged data? I was thinking along the lines of
NSPredicate(format: "%K != %#", HKPredicateKeyPathSource, "Health")//crash
This predicate did not work and crashed my program when I executed my query.
Does anyone know why it crashes, or if there is a better way to achieve my goal of weeding out the data that is user-entered?
Thanks.
Your crash could be probably due to the fact that currently, only the "=" and "IN" operators are supported for predicates filtering HKSamples by source
You could use a source query first to pull out all the sources and ignore the health app source (which has a bundle identifier of com.apple.Health), by using the following code:
- (void)fetchSources
{
NSMutableArray *dataSources = [[NSMutableArray alloc] init];
HKQuantityType *stepsCount = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];
HKSourceQuery *sourceQuery = [[HKSourceQuery alloc] initWithSampleType:stepsCount
samplePredicate:nil
completionHandler:^(HKSourceQuery *query, NSSet *sources, NSError *error)
{
for (HKSource *source in sources)
{
if (![source.bundleIdentifier isEqualToString:#"com.apple.Health"])
{
[dataSources addObject:source];
}
}
}];
[self.healthStore executeQuery:sourceQuery];
}
Once you have all the other sources other than the Health App, use a source predicate to pull data for all the other sources:
NSPredicate *sourcesPredicate = [HKQuery predicateForObjectsFromSources:[NSSet setWithArray:self.dataSources]]
Hope this helps.

Resources