I have updated my local JSON file but I cannot figure out why it is not being pushed to Firebase? For example, I created JSON file and used placeholder text just to see how it would look in the UI. I pushed the placeholder text to Firebase but when I updated my JSON file in Xcode, it did not get pushed and updated in Firebase. Do I need to make a new push method for that particular key/value pair?
Here is an example of what I pushed initially with the placeholder text
"id": 1,
"category": "Cardiovascular",
"course": {
"id": 1,
"image": "cardiovascular",
"description": "This quiz goes over the cardiovascular system.",
Here is the update to description that I want to push to Firebase.
"id": 1,
"category": "Cardiovascular",
"course": {
"id": 1,
"image": "cardiovascular",
"description": "The Cardiovascular system transports blood containing oxygen, nutrients, and other substances (e.g., hormones, electrolytes, and drugs) to the tissues of the body, whereas at the same time facilitating the removal of carbon dioxide and other waste products from the body. It also assists in temperature regulation. The primary components of the cardiovascular system include the heart, arteries, arterioles, capillaries, venules, veins, and blood. The heart is comprised of cardiac muscle and nervous tissue that fat generates the force that propels the blood through the body.",
Here is the method to push to Firebase
func pushToFirebase(quizmodules: [Quiz]){
let db = Firestore.firestore()
let firebaseModules = db.collection("quizmodules")
for quiz in quizmodules {
let course = quiz.course
let test = quiz.course.test
let firebaseModule = firebaseModules.addDocument(data: ["category": quiz.category])
firebaseModule.updateData(["id": firebaseModule.documentID,
"course": ["id": firebaseModule.documentID,
"image": course.image,
"description": course.description,
],
"test": [
"id": firebaseModule.documentID,
"questions": test.questions.count
]
])
for question in test.questions {
let firebaseQuestion = firebaseModule.collection("questions").addDocument(data: ["content": question.content,
"correctIndex": question.correctIndex,
"answers": question.answers
])
firebaseQuestion.updateData(["id": firebaseQuestion.documentID])
}
}
}
CodePudding user response:
Let me restate the question to make sure I am answering correctly:
I am writing a document to Firestore and want to update that document at a later time
When you want to update a specific document in Firestore, you need to know the documentId of the document you want updated.
So here's the issue
let firebaseModule = firebaseModules.addDocument(data:
.addDocument
creates a new document each time it's run so the following .update
call updates the document that was just created. The next time the code is run a totally new document is created.
Also, and maybe this is intentional, the .addDocument
call creates documents with a field category
["category": quiz.category])
and then just adds a bunch more fields to that same document.
firebaseModule.updateData(["id": firebaseModule.documentID,
"course": ["id": firebaseModule.documentID,
so every document looks the same
some_document_id
category: some value
course: [
description: some value
that could be simplified by just creating the document with the fields in the addDocument
call.
So - how to fix. Here's a very brief example that creates an initial document with a documentId of my_document
let tempCollection = self.db.collection("my_collection")
let myDocument = tempCollection.document("my_document")
myDocument.setData(["field0": "data0",
"field1": "data1"])
At a later time in your code, you want to update the values of field0
and field1
of my_document
. Here's how to do that
let tempCollection = self.db.collection("my_collection")
let myDocument = tempCollection.document("my_document")
myDocument.updateData(["field0": "new data0",
"field1": "new data1"])
The important bit is that the document being updated has the same documentId (my_document) as in the code that created the document.
CodePudding user response:
If you adopt some of the new Firestore Wrappers that are provided with FirebaseFirestoreSwift
you can save some of the complications.
Your model struct
s would change a little too
struct Quiz: FirestoreCodable{
@DocumentID var id: String?
var category: String
var course: Course
}
struct Course: FirestoreCodable{
@DocumentID var id: String?
var image: String
var description: String
}
FirestoreCodable
is just a protocol
to make your methods generic (reusable)
public protocol FirestoreCodable: Decodable, Encodable{
/// Wrap with `@DocumentID` from `import FirebaseFirestoreSwift`
var id: String? { get set }
}
Then you can add documents with
///Adds the object to the collection, returns the `id` for the newly created document
public func create<FC : FirestoreCodable>(path: String, object: FC) throws -> String?{
let reference = try store.collection(path).addDocument(from: object)
return reference.documentID
}
then use it
let documentId = try create(path:"quizmodules", object: quiz)
And update documents with
public func update<FC : FirestoreCodable>(path: String, object: FC) throws{
guard let id = object.id else{
throw PackageError.needValidId
}
try store.collection(path).document(id).setData(from: object)
}
then use it
try update(path:"quizmodules", object: quiz)
or
public func update<V: Hashable>(path: String, id: String, variableName: String, value: V) throws{
let reference = store.collection(path).document(id)
reference.updateData([
variableName: value
])
}
then use it
try update(path:"quizmodules", id: quiz.id, variableName: "course", value: course)
Note that quiz
and course
would be an object of type Quiz
or Course
Once you have the basic setup going you can also use
@FirestoreQuery(collectionPath: "quizmodules")
to listen for changes to the collection.