简体   繁体   English

将两个以上的 collections 从 Firestore 复制到另一个集合不起作用

[英]Copying more than two collections from firestore to another collection doesn't work

So I have four collections in my firestore database:所以我的 Firestore 数据库中有四个 collections:

  1. EnglishQuestions英语问题
  2. MathQuestions数学题
  3. ScienceQuestions科学问题
  4. DzongkhaQuestions宗卡问题

I am trying to copy all the data from those collections and put it under one collection for each user.我正在尝试从 collections 复制所有数据,并将其放在每个用户的一个集合中。 So it would look like this.所以它看起来像这样。

  1. username(collection)用户名(集合)
    • MathQuestions (doc) - Questions (collection) MathQuestions (doc) - Questions (collection)
    • EnglishQuestions (doc) - Questions (collection) EnglishQuestions (doc) - Questions (collection)
    • ScienceQuestions (doc) - Questions (collection) ScienceQuestions (doc) - Questions (collection)
    • DzongkhaQuestions (doc) - Questions (collection) However, when I am trying to do this, it act weirdly in the sense that sometimes, all the four collections gets copied in the username collection but other times only the first two collections or the first collection gets copied. DzongkhaQuestions (doc) - Questions (collection) 但是,当我尝试这样做时,它的行为很奇怪,有时,所有四个 collections 都被复制到用户名集合中,但其他时候只有前两个 collections 或第一个集合被复制。

Before I had the part where you call the database for each collection one after another.在我有你一个接一个地为每个集合调用数据库的部分之前。 Since that didn't work I tried to make each call a function of its own as seen below.由于这不起作用,我尝试将每个调用都设为自己的 function,如下所示。 Sadly that doesn't work as well.可悲的是,这也不起作用。 Any help would be greatly appreciated.任何帮助将不胜感激。

After taking @ralemos's suggestion, it still doesn't work but the new code looks like the following.接受@ralemos 的建议后,它仍然不起作用,但新代码如下所示。

    fire
      .auth()
      .createUserWithEmailAndPassword(this.state.email, this.state.password)
      .then((u) => {
        let user = fire.auth().currentUser;
        console.log(user);
        if (user != null) {
          user
            .updateProfile({
              displayName: this.state.name,
            })
            .then((r) => {
              let db = fire.firestore();
              let data = {
                name: this.state.name,
                email: this.state.email,
                college: this.state.college,
                dzongkhag: this.state.dzongkhag,
              };
              db.collection(this.state.email).doc("UserProfile").set(data);
              this.copyMathDatabase();
            });
        }
      });
  }
  copyMathDatabase() {
    let db = fire.firestore();
    db.collection("Questions")
      .get()
      .then((snapshot) => {
        snapshot.forEach((doc) => {
          db.collection(this.state.email).doc("MathQuestions").collection("Questions").doc(doc.id).set({
            Category: doc.data().Category,
            Choice: doc.data().Choice,
            CorrectAnswer: doc.data().CorrectAnswer,
            IsCorrectAnswer: doc.data().IsCorrectAnswer,
            IsWrongAnswer: doc.data().IsWrongAnswer,
            Question: doc.data().Question,
            UserHasNotResponded: doc.data().UserHasNotResponded,
            Marked: doc.data().Marked,
          });
          console.log("Math Questions: ", doc.id);
        });
        this.copyEnglishDatabase();
        console.log(" Done copying the Math database ");
      });
  }

  copyEnglishDatabase() {
    let db = fire.firestore();
    db.collection("EnglishQuestions")
      .get()
      .then((snapshot) => {
        snapshot.forEach((doc) => {
          db.collection(this.state.email).doc("EnglishQuestions").collection("Questions").doc(doc.id).set({
            Category: doc.data().Category,
            Choice: doc.data().Choice,
            CorrectAnswer: doc.data().CorrectAnswer,
            IsCorrectAnswer: doc.data().IsCorrectAnswer,
            IsWrongAnswer: doc.data().IsWrongAnswer,
            Question: doc.data().Question,
            UserHasNotResponded: doc.data().UserHasNotResponded,
            Marked: doc.data().Marked,
            Passage: doc.data().Passage,
            isPassageQuestion: doc.data().isPassageQuestion,
          });
          console.log("English Questions: ", doc.id);
        });
       
        console.log("Done copying the English database");
      });
  }

Remember, many/most Firestore calls return a promise - which means the result of an operation to be returned later, possibly much later.请记住,许多/大多数 Firestore 调用都会返回promise - 这意味着稍后会返回操作的结果,可能会晚。 Just putting one call after the other does NOT mean one will wait for the other - that isn't at all what promises do.一个接一个接一个电话并不意味着一个会等待另一个——这根本不是 promise 的作用。 You may have seen some code that uses async/await, which LOOK like they wait for each other - but it's just "syntactic sugar" (ie makes it look good) that hides the fact that there are STILL promises "behind the scenes".您可能已经看到一些使用 async/await 的代码,它们看起来像是在相互等待——但它只是“语法糖”(即让它看起来不错)隐藏了“幕后”仍然存在承诺的事实。

For your example, I would do the following:对于您的示例,我将执行以下操作:

copyMathDatabase() {
    let db = fire.firestore();
    return db.collection("Questions")
    ...
}

copyEnglishDatabase() {
    let db = fire.firestore();
    return db.collection("EnglishQuestions")
    ...
}

Note the "return" - each function now returns the PROMISE of a result, which will happen sometime later.请注意“返回” - 每个 function 现在返回结果的PROMISE ,这将在稍后的某个时间发生。 Then, in your auth function area:然后,在您的授权 function 区域:

  fire
      .auth()
      .createUserWithEmailAndPassword(this.state.email, this.state.password)
      .then((u) => {
        let user = fire.auth().currentUser;
        console.log(user);
        if (user != null) {
          user
            .updateProfile({
              displayName: this.state.name,
            })
            .then((r) => {
              let db = fire.firestore();
              let data = {
                name: this.state.name,
                email: this.state.email,
                college: this.state.college,
                dzongkhag: this.state.dzongkhag,
              };
              return db.collection(this.state.email).doc("UserProfile").set(data);
            })
            .then(() => {
              return this.copyMathDatabase();
             })
            .then(() => {
              return this.copyEnglishDatabase();
            };
        }
      });
  }

note - the result of the.set() returns a PROMISE to be completed when it is done;注意 - the.set() 的结果返回一个PROMISE完成后完成; .then() waits for that promise then executes copyMathDatabase(), which returns a PROMISE to be completed when it is done; .then() 等待 promise然后执行 copyMathDatabase(),完成后返回PROMISE完成; .then() waits for that promise then executes copyEnglishDatabase(), which returns a PROMISE to be completed when it is done. .then() 等待 promise然后执行 copyEnglishDatabase(),它在完成后返回PROMISE完成。

This question shows you have very very little understanding of exactly what promises are - and that understanding is absolutely critical and necessary to using Firestore.这个问题表明您对 Promise 的确切含义知之甚少——而这种理解对于使用 Firestore 是绝对关键和必要的。 You need to go and teach yourself promises in detail before you continue.在继续之前,您需要 go 并详细自学承诺。 You should also learn what the aync/await syntax is, and what it actually does.您还应该了解 aync/await 语法是什么,以及它的实际作用。 This is NOT the place for you to learn these things.这不是你学习这些东西的地方。

This is very likely to be a synchronicity issue caused by calling copyMathDatabase() and copyEnglishDatabase() , which are both asynchronous, in sequence, try changing that block of your code to the following:这很可能是由调用copyMathDatabase()copyEnglishDatabase()引起的同步问题,它们都是异步的,依次尝试将代码块更改为以下内容:

db.collection(this.state.email).doc("UserProfile").set(data).then(() =>{
    this.copyMathDatabase().then(() => {
        this.copyEnglishDatabase();
    });
});

This way your are forcing your code to be executed in the proper order and mitigating errors, and this should fix the issue you are facing.这样您就可以强制您的代码以正确的顺序执行并减少错误,这应该可以解决您面临的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM