Querying below AutoID's in Firebase
Firebase Database queries properties one level deeper than the location where you run them. They cannot contain a dynamic path under that.
Since you're querying from /Results
, you can order by/filter on properties under /Results/$id/PropertyName
.
To allow ordering/filtering of all items on properties under /Results/$id1/$id2/PropertyName
you will need to change/augment your data structure. For example:
ResultValues
-auto_generated_ID1_auto_generated_ID2_value1
value: abc
path: "auto generated ID/auto generated ID"
-auto_generated_ID1_auto_generated_ID2_value2
value: def
path: "auto generated ID/auto generated ID"
Now you can query with:
ref.child("ResultValues")
.queryOrderedByChild("value")
.queryEqual(toValue: "def")
.observeSingleEvent(of: .value, with: {(snapshot) in
print(snapshot) })
Firebase Query Under AutoID Under Child Swift
The Firebase Realtime Database is a NoSQL database, and it's only possible to filter by direct descendents of children in a list. Therefore, you will need to use a flatter data structure, and avoid splitting your fields into basicInfo
, fullInfo
:
users
|- userId
|- name: "John"
|- age: 17
|- gender: "m"
|- birthday: "10.10.2000"
...
With this approach, you can attach a listener to the users
node and then filter by child values using the queryOrderedByChild
and queryEqualToValue
methods. For example, something like this in Swift:
Database.database().reference().child("users").queryOrderedByChild("name").queryEqualToValue("(some name)").observeSingleEventOfType(.Value, with: { snap in
// Do your thing with snap
})
With either of your structures, you can limit your results with the queryLimitedToFirst
and queryLimitedToLast
methods. For example, from the filtering data section of the documentation:
The following example demonstrates how example blogging app retrieves a list of the 100 most recent posts by all users:
// Last 100 posts, these are automatically the 100 most recent
// due to sorting by push() keys
let recentPostsQuery = (ref?.child("posts").queryLimited(toFirst: 100))!
For more details on filtering and limiting Firebase data in Swift/iOS, see the working with lists of data on iOS documentation.
How to get value from autoID in Firebase Database - Swift
The easiest way to get the count of guests who are marked as attending is to use a query:
let ref = Database.database().reference().child("userInfo").child(uid!)
let query = ref.child("guests").queryOrdered(byChild: "attending").queryEqual(toValue: "attending")
query.observe(.value) { snapshot in
let numberOfusers = snapshot.childrenCount
print(snapshot.childrenCount)
}
Reading Data stored via Autoid from Firebase Swift
The way I usually do this is by:
ref.child("Phrases").observeSingleEvent(of: .value, with: { snapshot in
let value = snapshot.value as! [String:Any]
let name = value["phrase"] as? String ?? ""
})
Alternatively you could unwrap it first
ref.child("Phrases").observeSingleEvent(of: .value, with: { snapshot in
if let value = snapshot.value as? [String:Any] {
let name = value["phrase"] as? String ?? ""
}
})
Accessing Firebase Data inside unique AutoID
The issue you're having is that you're trying to dig deeper but can't as you don't have a hold of that id. You'll want to use the .childAdded
in your reference observation when you want to get inside of a list in your JSON tree when you don't have a hold of that id to get inside - this will be called as many times as there are values inside of Category 1 tree:
let reference = Database.database().reference()
reference.child("Category 1").child("optionSelected").observe(.childAdded, with: { (snapshot) in
let uniqueKey = snapshot.key // IF YOU WANT ACCESS TO THAT UNIQUE ID
print(uniqueKey)
guard let dictionary = snapshot.value as? [String: AnyObject] else { return }
let date = dictionary["date"] as? String
let variableOne = dictionary["Variable 1 Float"] as? Float
let variableOne = dictionary["Variable 2 Float"] as? Float
}, withCancel: nil)
You may also want to avoid using spaces in your database keys to avoid any problems in the near future. I'd stick with the common lowercased underscore practice e.g. "category_1" or "variable_2_float"
Swift 3 and Firebase: Retrieve auto id value from snapshot
.value returns the parent node and all of the child nodes that satisfy the results of the query. In this case, the children would need to be iterated over (there could be more than 1 child that matches the query).
The snapshot.key is the parent node key (bS6JPkEDXIVrlYtSeQQgOjCNTii1) and the value is a snapshot (dictionary) of all of the children. Each of those children is a key:value pair of uid:value and value a dictionary of the child nodes, receiverId, senderId etc
This code will print the uid of each child node and one of the values, timestamp, for each user node that matches the query.
let usersRef = ref.child("users")
let queryRef = usersRef.queryOrdered(byChild: "receiverId")
.queryEqual(toValue: "LKupL7KYiedpr6uEizdCapezJ6i2")
queryRef.observeSingleEvent(of: .value, with: { (snapshot) in
for snap in snapshot.children {
let userSnap = snap as! FIRDataSnapshot
let uid = userSnap.key //the uid of each user
let userDict = userSnap.value as! [String:AnyObject]
let timestamp = userDict["timestamp"] as! String
print("key = \(uid) and timestamp = \(timestamp)")
}
})
query mid-section of firebase database in swift
There's a couple of ways to do this but an easy solution is to keep a total_count in another node and an index within each node.
Then use queryStartingAtValue and queryEndingAtValue to query the range of child nodes you are interested in.
When you add a child to your 'posts' node for example, add one to the total_count node and save it. Over time you'll have 100 posts and the total_count node will have a value of 100. You can then query for any range of posts: .queryStartingAtValue(80) and . queryEndingAtValue(89), or .queryStartingAt(20) and .queryEndingAt(30)
For example, assume there's 45 posts (showing just 4 of them here)
posts
...
post_1024
text: "my post!"
index: 42
post_1025
text: "another post"
index: 43
post_1026
text: "yippee"
index: 44
post_1027
text: "Stuff and Things"
index: 45
and then a node to track them
post_info
total_count: 45
and the code to query for the middle two nodes
let ref = myRootRef.childByAppendingPath("posts"
ref.queryOrderedByChild("index").queryStartingAtValue(43).queryEndingAtValue(44)
.observeEventType(.Value, withBlock: { snapshot in
print(snapshot.key)
})
and the output would be
post_1025
text: "another post"
index: 43
post_1026
text: "yippee"
index: 44
That being said, this may be slightly redundant depending on what happens to your data. If you never delete posts, then you're set. However, if you delete posts then obviously there's a gap in your indexes (42, 43, .. 45) so other factors need to be taken into consideration.
You may not even need a total_count - it just depends on how your app works.
You could also leverage the priority variable on your nodes to store the index instead of having it be a child node.
Transitions and .observeSingleEvent with .Value and .numChildren can be also be used to obtain a live node count.
Related Topics
Class 'Viewcontroller' Has No Initializers in Swift
Convert Avaudiopcmbuffer to Nsdata and Back
Hide/Show Tab Bar When Push/Back. Swift
How to Get Rgb Components from Color in Swiftui
Is There a Zip Function to Create Tuples with More Than 2 Elements
Swift: Property Conforming to a Specific Class and in the Same Time to Multiple Protocols
How to Create Dictionary That Can Hold Anything in Key? or All the Possible Type It Capable to Hold
What's the Difference Between Aranchor and Anchorentity
Do Swift Inner Classes Have Access to Self of Outer Class
Add "For In" Support to Iterate Over Swift Custom Classes
How to Convert Timeinterval into Minutes, Seconds and Milliseconds in Swift
How to Override Trait Collection for Initial Uiviewcontroller? (With Storyboard)
Swift Sphere Combine Star Data
Remove Element from Collection During Iteration with Foreach