从另一个“ getDocument”查询中的“ getDocument”查询中检索数据

时间:2018-10-11 09:53:18

标签: ios swift google-cloud-firestore

我在从Firestore检索数据的代码中遇到问题。

我的代码中有2个类:锻炼和标记。 我的FirestoreDatabase中有2个集合:练习和标签

我需要从“锻炼”集合中获取所有“锻炼”文档。每个“练习”文档都有一个称为“标签”的字段,该字段是字符串数组。数组的每个字符串均包含“ id”,该id表示“ tag”在“ tags”集合上具有的文档。因此,在“标签”集合中查询此ID,使我能够获取正确的“标签”文档并访问其所有数据。这正是我要在代码中执行的操作。

我需要将所有练习合并到一个Exercise对象中,为此,我必须在另一个getDocument查询中使用getDocument查询,以便从“标签”集合中获取练习的“标签”

这是我的课程标记和练习:

class Tag {  
var id: String?
var type: String?
var description: String?

init(id: String, type: String, description: String) {
    self.id = id
    self.type = type
    self.description = description
  }
}

class Exercise {
   let id: String?
   let group: String?
   let tags: [Tag]
   let title : String!

   init(id: String, group: String, tags: [Tag], title: String){  
    self.id = id
    self.group = group
    self.tags = tags
    self.title = title   
  }

}

这是我从Firestore数据库中获取“练习”的代码:

func fetchExercises(completion: @escaping ([Exercise]) -> ()) {

    let exercisesRef = Firestore.firestore().collection("exercises")

    exercisesRef.getDocuments() { (querySnapshot, err) in

        var exercisesArray = [Exercise]()

        if let err = err {
            print("Error getting documents: \(err)")
        } else {
            for document in querySnapshot!.documents {
                //print("\(document.documentID) => \(document.data())")

                let myData = document.data()
                let exercise_ID = document.documentID
                let exercise_group = myData["Group"] as! String
                let tagsArray = myData["Tags"] as! [String]

                var exercise_tags: [Tag] = [Tag]()

                for tag in tagsArray {
                    let tagID: String = tag
                    fetchTagfromID(tagID: tagID) { (tag: Tag) in
                        exercise_tags.append(tag)
                    }
                }

                let exercise_title = myData["Title"] as! String                 

                exercisesArray.append(Exercise(id: exercise_ID,
                                               group: exercise_group,
                                               tags: exercise_tags,
                                               title: exercise_title,
                ))
            }
            DispatchQueue.main.async{
               print("EXERCISE FETCH HAS FINIS")
                completion(exercisesArray)
            }
        }
    }
}


func fetchTagfromID(tagID: String, completion: @escaping (Tag) -> ()) {


let tagRef = Firestore.firestore().collection("tags").document(tagID)

tagRef.getDocument() { (document, err) in

    if let err = err {
        print("Error getting documents: \(err)")
    } else {

        let myData = document?.data()

        let tagDescription: String = myData!["description"] as! String
        let tagType: String =  myData!["type"] as! String
        let tag: Tag = Tag(id: tagID, type: tagType, description: 
tagDescription)


        DispatchQueue.main.async{
            print("TAGS FETCH HAS FINISHED")
            completion(tag)
        }
    }
  }
}

我的问题与执行时序(队列)代码有关。

我需要先填充“ exercise_tags”(第二个getDocument查询),然后继续并完成fetchExercise(主getDocument查询),但是Firestore不允许(或不知道如何)执行该操作。代码首先完成主要的getDocument查询(fetChExercises),然后返回完成次要的getDocument查询(fetchTagfromID)。

总而言之,我需要在运行时获取以下日志:

TAGS FETCH HAS FINISHED
EXERCISES FETCH HAS FINISHED

现在我正相反。

您知道家伙如何解决这个问题吗?也许正在更改调度队列...

我现在如何分两步解决问题,但是优雅的解决方案是一步完成所有事情。这是fetchExercises。

谢谢!

1 个答案:

答案 0 :(得分:0)

因此,您需要做的是获取一个练习的所有标签,然后获取另一个练习。并最终获取调用完成处理程序以更新UI。我对代码进行了一些更改,您可以对其进行检查。

   var exercisesArray = [Exercise]()
   var listFromFetchExercise = []()  //it will contain all object of array 
   querySnapshot!.documents. set DataType according to that.
   var completion_exercises_Listner: () -> ()

   func fetchExercises(completion: @escaping ([Exercise]) -> ()) {

   let exercisesRef = Firestore.firestore().collection("exercises")

exercisesRef.getDocuments() { (querySnapshot, err) in

    if let err = err {
        print("Error getting documents: \(err)")
    } else {

        listFromFetchExercise = querySnapshot!.documents
        fetchAllExercise()

        DispatchQueue.main.async{
           print("EXERCISE FETCH HAS FINIS")
            completion(exercisesArray)
        }
    }
}
}

func fetchAllExercise(completion: @escaping ([Exercise]) -> ()){

fetchExercise()
completion_exercises_Listner = {
    completion(exercisesArray);
}

}

func fetchExercise(index:Int = 0) {

  let document = listFromFetchExercise[index]

  let myData = document.data()
  let exercise_ID = document.documentID
  let exercise_group = myData["Group"] as! String
  let tagsArray = myData["Tags"] as! [String]

  var exercise_tags: [Tag] = [Tag]()

  fetchTagsFromIDS(tagsArray) { (tag: [Tag]) in
  exercise_tags.append(contentsOf: tag)

  let exercise_title = myData["Title"] as! String                 

  exercisesArray.append(Exercise(id: exercise_ID,
                               group: exercise_group,
                               tags: exercise_tags,
                               title: exercise_title,

   DispatchQueue.main.async{
      exercisesArray.append(tag)
      if (index + 1) < exercisesArray.count {
        fetchExercise(index+1,)
      }else{
        //Done
        completion_exercises_Listner()
      }

  }
   ))

  }



 var listofTags = [String]()
 var resultofTags = [Tag]()

   func fetchTagsFromIDS(tagIDS:[String],completion: @escaping (_ tags:[ 
 String]) -> ()){

listofTags = tagIDS;
fetchTagfromID() //Start With first tag

completionListner = {
    completion(resultofTags);
}

}

var completionListner: () -> ()

func fetchTagfromID(index:Int = 0) {

 let tagRef = Firestore.firestore().collection("tags").document(tagID)

 tagRef.getDocument() { (document, err) in

if let err = err {
    print("Error getting documents: \(err)")
} else {

    let myData = document?.data()

    let tagDescription: String = myData!["description"] as! String
    let tagType: String =  myData!["type"] as! String
    let tag: Tag = Tag(id: tagID, type: tagType, description: 
   tagDescription)


    DispatchQueue.main.async{
        print("TAGS FETCH HAS FINISHED")
        resultofTags.append(tag)
        if (index + 1) < listofTags.count {
          fetchTagfromID(index+1,)
        }else{
          //Done
          completionListner()
        }
        //completion(tag)
    }
}
} }