Firebase Swift equivalent of push() - ios

In Javascript, calling push on a firebase ref would generate a random ID. Then you can populate the stuff below.
However, I can't find push in Swift. Do I have to generate random IDs myself?

I think you're looking for childByAutoId():
childByAutoId generates a new child location using a unique key and returns a FIRDatabaseReference to it. This is useful when the children of a Firebase Database location represent a list of items.
The unique key generated by childByAutoId: is prefixed with a client-generated timestamp so that the resulting list will be chronologically-sorted.
Declaration
func childByAutoId() -> FIRDatabaseReference
Also see: https://firebase.google.com/docs/database/ios/read-and-write#update_specific_fields

Related

how save data to Firebase Firestore with a custom but unique Id?

In swift using Firebase, with:
let ref = dbLocations.collection("Data").document()
ref.setData(data)
Data added with a document Id like 40rprS6NshDHhZiI8YxJ
how can I generate an ID as "location1" "location2" or something but with the guarantee the is a unique one on the database?
If you want to set your own ID then you just have to specify it in document() as shown below:
let ref = dbLocations.collection("Data").document("CUSTOM_ID")
ref.setData(data);
This however will overwrite the document if it already so you must check if document exists before writing data. You could use .setData(data, merge: true) so if document exists it'll update it instead of totally replacing current data if that suits your requirements.
How can I generate an ID as "location1" or "location2"
Using sequential document IDs is considered an anti-pattern when it comes to Firestore:
Do not use monotonically increasing document IDs such as:
Customer1, Customer2, Customer3, ...
Product 1, Product 2, Product 3, ...
Such sequential IDs can lead to hotspots that impact latency.
So you can create your own unique IDs, as long as you are 100% sure that those IDs are unique.
Moreover, each time you call .document() without passing any argument, a new document ID is generated. If you need to have a custom ID then you should consider using:
let ref = dbLocations.collection("Data").document("idOfYourChoice")

Append element to Firebase Array

How I could append an element to an array like that:
Using this code I'm overriding the old data:
let toUpdate = [book.id]
self.refUsers.child(localUser.key!).child("booksPurchased").setValue(toUpdate, withCompletionBlock: { (error, _) in
You could use this method: firebase.firestore.FieldValue.arrayUnion()
Example with angularfire2:
this.afs.collection('collection').doc(id).update( {
array: firebase.firestore.FieldValue.arrayUnion( 'newItem' )
});
For more information: https://firebase.google.com/docs/reference/js/firebase.firestore.FieldValue#arrayunion
In this case, you will have to read the existing data, then write it back with the new value added. Arrays like this are not always the best way to store lists of data if you want to perform a lot of append operations. For that, you're better off pushing data into a location using childByAutoId.
Reading and writing lists
Append to a list of data
Use the childByAutoId method to append data to a list in multiuser applications. The childByAutoId method generates a unique key every time a new child is added to the specified Firebase reference. By using these auto-generated keys for each new element in the list, several clients can add children to the same location at the same time without write conflicts. The unique key generated by childByAutoId is based on a timestamp, so list items are automatically ordered chronologically.
You can use the reference to the new data returned by the childByAutoId method to get the value of the child's auto-generated key or set data for the child. Calling getKey on a childByAutoId reference returns the auto-generated key.
You can use these auto-generated keys to simplify flattening your data structure. For more information, see the data fan-out example.
-https://firebase.google.com/docs/database/ios/lists-of-data
You could set the values of the keys in the array to true, and then set the value directly in an update.
So if 'newId' is the new item to add, maybe something like:
const update = {
[`/users/${localUser.key}/booksPurchased/${newId}`]: true]
}
firebase.db.ref().update(update);
Firebase docs example of an update:
https://firebase.google.com/docs/database/web/read-and-write

Firebase: What's the correct way to update values?

If my database structure is like this:
and I have this:
ref = Database.database().reference().child(passUserID)
ref?.child("wins").updateChildValues("wins": numerator)
where numerator = (games played beforehand) + (games played after logging in), for the second statement it is giving me an error in the expression that I don't know how to fix.
Also if I try to do this instead:
ref?.child("wins").setValue(numerator)
it messes up my data bad and gives a bad instruction error.
The updateChildValues method takes a Dictionary. So you just need to call the method with a dictionary containing the key-value pairs you want to update, i.e.
ref = Database.database().reference().child(passUserID)
ref?.updateChildValues(["wins": numerator])
For more on how to read/write data to firebase realtime database, refer to: https://firebase.google.com/docs/database/ios/read-and-write
If you use .setValue triggers only in the beginning. Instead of .setValue use updateChildValues(.values/.childAdded/.childRemoved etc..) to update the values inside your tree. It will be executed whenever changes occurs to your node.
How to update particular value of child in Firebase DB

When I try to save data to Firebase it only updates the existing data, Swift, Firebase

The way I set up my database structure was like this:
It starts with Lists then there is a child that shows the users UID then inside that there is one item.
The one item inside the UID gets updated every time I attempt to save new data. Instead of adding another item the same one just keeps changing. I was wondering how I could instead of update the same one item every time add more items.
The way that I save my data is with this line of code.
let user = FIRAuth.auth()?.currentUser
let item: String = self.ItemTextField.text!
self.ref.child("Lists").child(user!.uid).setValue(["Items": item])
More idiomatic is to store the list of items with so-called push ids:
Lists
twEymn...
-Km....: "Yoghurt"
You'd do this with:
self.ref.child("Lists").child(user!.uid).childByAutoId().setValue(item)
The childByAutoId() generates a unique, sequential ID. It's similar to an array index, but this one works reliably in multi-user environments and when users can be offline. Read this blog post about these so-called push ids.
Alternatively you can use the name of the item as the key (if the item has to be unique in the list):
Lists
twEymn...
"Yoghurt": true
In that case the code becomes:
self.ref.child("Lists").child(user!.uid).child(item).setValue(true)
One thing you'll note is that both of these approaches only deal with the newly added item, instead of the list of items as a whole. This is a general pattern you'll see when using Firebase. By isolating your modifications, your app will be more scalable without users getting into each other's way.
The problem is that you are setting a key-value pair ("Items" : item) so that each time it is updating the value for the same key. What you could do instead is ("Items" : [your array of items here]), which will update a list of items for the same key each time.
You could also fetch the current list of items, append your new item locally, and then update.

Firebase: Swift - Query value in child node without knowing the parent key

I have a firebase database which I have imported a list of approx. 8200 Universities with the details seen above.
I want to be able to enter an email address into a text field then query the "domain" part of this JSON. My issue is I need to query all the domains in the list of 8000, however I do not know how to search domain ad I do not have the "7542" to use a childByAppendingPath.
So I have a reference to "universities" but I need to be able to query "domain" without knowing the parent key (i.e. 7542 in the example above, but I want to search the domain, "iautb.ac.ir").
You need to create a reference and Query that reference, check this link to find more about how to retrieve data from firebase.
Basically you need to do something like this
let myRef = Firebase(url: "https://your.firebaseio.com/universities")
let query = myRef.queryOrderedByChild("domain").queryEqualToValue("yourDomainSearchValue")
and then observe the events you need to on your query

Resources