Querying Below Autoid's in Firebase

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



Leave a reply



Submit