Update a Parent Title in Firebase Realtime DB in Swift - swift

I am trying to update one of the parents in my database. However, I am unsuccessful. Here is what the DB looks like:
I am able to Update the description and due date like so:
taskRef = Database.database().reference(withPath: "Tasks").child(titleOfTask)
taskRef?.updateChildValues(["Due Date": date_time])
taskRef?.updateChildValues(["Description": taskDescription])
However, I am trying to figure out how to update the name of the task. For example, if the user is trying to update the description of task "Alpha" and also decides to rename the task as well, how can I update the name?
I first tried to do this, but it didn't work, it just created and another key, value pair under the "Alpha" parent.
newTaskRef?.updateChildValues([titleOfTask: taskTitle])
Then I realized that my database reference is to the Task Title already, so it wouldn't have worked. Then I thought about creating another database reference to just "Tasks", and updating the title like so:
newTaskRef = Database.database().reference(withPath: "Tasks")
newTaskRef?.updateChildValues([titleOfTask: taskTitle])
But this didn't work either. Not sure what else I could try, or where I am going wrong.
Important Things:
taskTitle holds the new input the user enters
titleOfTask is the old name of the task. (i.e, used as a reference to read from DB)
in other words:
If the user wants to edit the "Alpha" Task, we would have to pass the STRING "Alpha" to the database.reference so we can read its values and update the description and/or due date. So the original Title of Task is stored in "titleOfTask", and the new task title would be stored in "taskTitle"

You can't directly change the keys in the DB. Instead you can follow a 2 step approach:
Create a new key with the updated title and info.
Delete the old key from the DB

Related

Check for existing value inside of Firebase Realtime Database

Hello, I have a problem I created a Registration form and im trying to check if there is any user which have a certain username inside the Firebase Db. I tried to get the reference of all the users.
var users = Database.database().reference("users")
But I don't know how I could check if there is any user with a specified username.
You'll want to use a query for that. Something like:
let query = users.queryOrdered(byChild: "username").equalTo("two")
Then execute the query and check whether the result snapshot exists.
Note though that you won't be able to guarantee uniqueness in this way. If multiple users perform the check at the same time, they may both end up claiming the same user name.
To guarantee a unique user name, you will need to store the user names as the key - as keys are by definition unique within their parent node. For more on this, see some of these top search results and possibly also from here.

Deleting parent node with child value

I am struggling to overcome to issue I have. I am trying to delete a parent node/key given I find the correct child value.
My database is structure liked this
I am querying my database by a certain value, objectID, as it will match the postID which is passed through the parameters. The objectID value is removed. However, I am struggling to remove the key in which it falls under.
I have had mixed results so far:
I can either remove the objectID value using this code:
refSnap?.ref.child("objectID").child(postID).removeValue()
Of I can remove the whole notifications node/directory, using this:
refSnap?.ref.child("objectID").queryEqual(toValue: postID).ref.removeValue()
refSnap?.key gives me all the keys/nodes under the notifications node.
I cannot access the key which the objectID and all other information is stored under as it is .childByAutoId. Can anyone possibly help me as to how I can sort this issue?
While the other answer provides some insight with an alternate and workable structure, the ability to delete a node based on a child is fairly straightforward and directly addresses the question without changing the structure.
(note that the structure may need to be changed anyway but for this exercise, we'll use it as is.)
Given a structure suggested in the question:
notification
"rtupy..." //childByAutoId
"-LFEMjAcny..." // childByAutoId
"-LFEzrrq..." // childByAutoId
from: "aw,sdasdad"
objectID: "-LFEMjAcn...."
timestamp: 15292
type: "comment"
Suppose you want to delete the node "-LFEzrrq..." as shown in your screenshot. That node contains the child objectID: "-LFEMjAcn...."
To delete the node you need query for the node that contains the objectID you want which, according to the question, is working and returning the correct child.
Use the returned snapshot to obtain it's parent key, and get the path to that node and delete it. Note that we don't know what process or code the OP used to obtain the node they want to delete - perhaps it was from another query and the node reference was passed in or some other means.
let queryRef = //unknown how, but build the query for objectID = "-LFEMjAcny...."
queryRef.observeSingleEvent(of: .value, with: { snapshot in
let key = snapshot.key //this is the parent key of the objectID node i.e. -LFEMzrrq..."
let parentRef = snapshot.ref.parent! //this is the path to that parent
let refToDelete = parentRef.child(key) //add the parent key to the path: -LFEzrrq
refToDelete.removeValue() //delete it
})
As you can see, regardless of the parent nodes' key, or how deep it is, this code will delete the node found in the query.
The key names do not matter so using .childByAutoId as references to tie your nodes together is safe and generally best practice as disassociating node keys from the data they contain makes your structure highly expandable.
Your issue is that you are using childByAutoId and you can't "tie" these random alphanumerics to something(in this case the post).
The structure that i would set is this:
-notifications
--uid //notifications for user
--- userAid+userBid //follow notification, if they unfollow you already now which one it is and you can go and delete it
---commentNotificationID // you give this notification the same Id that the comment has, so if the user deletes the comment you use that id to delete the notification as well.

How to set more than one value to a child in Firebase using Swift?

I am trying to make a money related app which shows the user their spendings as a project to get used to Firebase. So I stumbled upon this issue; I can't seem to figure out how to add more than one expense assigned to a user. Whenever I add a new expense, the existing value in Firebase gets reset to the new value but I want it to store both the new and the old value. How can I do this?
There's something called "autoID" if that helps. I'll link that in a few moments.
Edit: It's used here.
childByAutoId() is what you want for swift. See Updating Or Deleting specific data section in the Read and Write Data on iOS
let thisUserRef = ref.child("users").child(users uid)
let expenseRef = thisUserRef.child("expenses").childByAutoId()
let dict = ["expense_type": "travel", "expense_amt": "1.99"]
expenseRef.setValue(dict)
will results in
users
uid_0
-Y88jn90skda //<- the node key created with childByAutoId
expense_type: "travel"
expense_amt: "1.99"
the childByAutoId is super powerful and allows 'random' node keys to be generated that contain your child data.
See the answer to this question and this other question for some tips on data modeling and queries.

What is a CloudKit RecordID

While starting to work more with CloudKit I just realized that I don't actually know what a RecordID is...
I'm looking at the CloudKit dashboard right now, I see RecordTypes, RecordName etc, but I don't see RecordID. The iOS Dev library mentions RecordID a lot, but never actually tells what it is or where to find it.
I guess I'm just dumb, but I can't figure it out.
Every record has a record Id, which is a CKRecordID instance, and the class has a name property. If you don't specify a name, new records will have a record Id with a name that is a GUID.
You can only fetch with record Id if you know it, and in most instances you will let Cloud Kit create on for you, and you won't store it locally, so you won't know it.
Every CKRecord has a bunch of metadata, which includes the record id. See the list here.
Here a snapshot of the dashboard, your recognised it. You can either accept the recordIDs that CloudKit gives you or generate your own [although they must be unique within your database instance]. Here the screenshot
And here a small code snippet to show you how to create your own ID, using the same method I suspect CloudKit uses.
let uniqueReference = NSUUID().UUIDString
let uniqueRecordID = CKRecordID(recordName: uniqReference)
let newRecord = CKRecord(recordType: "Collection", recordID:uniqueRecordID)

Is it possible to store hidden metadata information that is tied to a specific Table or Cell within a Word document?

I am trying to store metadata (basically a unique id) along with each cell of a table in a Word document. Currently, for the add-in I'm developing, I am querying the database, and building a table inside the Word document using the data that is retrieved.
I want to be able to save any of the user's edits to the document, and persist it back to the database. My initial thought was to store a unique id along with each cell in the table so that I would be able to tell which records to update. I would also like to store some sort of "isChanged" flag within each cell so that I could tell which cells were changed. I found that I could add the needed information into the "ID" property of the cell - however, that information was not retained if the user saved the document, closed it, and re-opened it. I then tried storing the data by adding a data to the "Fields" collection - but that did not work and threw a runtime error. Here is the code that I tried:
object t1 = Word.WdFieldType.wdFieldEmpty;
object val = "myValue: " + counter;
object preserveFormatting = true;
tbl.Cell(i, j).Range.Fields.Add(tbl.Cell(i, j).Range, ref t1, ref val, ref preserveFormatting);
This compiles fine, but throws this runtime error "This command is not available".
So, is this possible at all? Or am I headed in the wrong direction?
Thanks in advance.
Wound up using "ContentControls" to store the information I needed. I used the "Title" field to store the unique id, and the "tag" field to track whether the field had been changed or not. See this link for more info: http://blogs.technet.com/gray_knowlton/archive/2010/01/15/associating-data-with-content-controls.aspx
Since a "Word 2007 Document" is XML, you can add a namespace to the document then adore the elements with attributes from your namespace. Word should ignore your namespace when loading and saving. Moreover, you can add new elments to store any information (metadata) needed.
With that said, I have not used this technique with Word, but I have done it successfully using Excel 2003.
First thing to try, is create a bare "Word 2007 Document". In your case, add a simple two by two table. Open it with a text or XML editor and add your namespace, and adore an attribute and add an element. Open with Word make a change then save it. Open with editor and make sure your namespace attribute and element have not been changed.