当前位置: 首页 > 知识库问答 >
问题:

我可以用什么方法在Firebase Firestore中正确地创建数据结构,以建立多对多关系模型,从而在vue js中检索特定的UID

赵俊侠
2023-03-14

我知道这类问题已经被问过很多次了,但我还没有找到一个足够有意义的例子来执行,所以我把我的具体案例带到会议桌上,以获得澄清。

问题摘要:这个问题源于使用Vue路由器。在这个项目中,我们有一个用户,他可以创建自己的团队,并将团队成员添加到该团队中。最初,我得到了我想要的结果,因为我正在寻找的数据流按照预期工作,使用路由器链接中的道具为细节视图提供了这样的数据

this.members = this.$route.params.data

团队列表将显示在罚款和单击按钮,以查看特定团队的成员也工作。我的问题的开始是来自路由器链接的数据没有持久化,当刷新或更改页面以添加新团队成员时,当我使用this.$router.back()方法时,团队成员列表不会更新它也不会按预期显示router.push({path:'home'})方法。

在进一步研究了路由器链接如何与Vue一起工作,并阅读了类似情况用户的一些SO帖子之后,我意识到我需要一种更好的方法来检索我想要的数据,只需使用:to=“{name:'pagethawshowSteamMembers',params:{id:id}}方法,而这正是我遇到的似乎是死胡同的地方。

我当前的数据结构是什么样子的:在Firestore中,我使用顶级集合来存储团队。文档id是当前用户的uid,文档中包含团队信息字段和存储团队成员的数组。

我如何尝试将数据添加到Firestore中:我探索了几种方法来存储团队成员信息以供检索

let ref = db.collection("Teams").doc(firebase.auth().currentUser.uid).collection("Team Members");

ref.set({
  // team member info
})

let ref = db.collection("Teams").where("userId", "==", firebase.auth().currentUser.uid);
ref.get().then(querySnapshot => {
  querySnapshot.forEach(doc => {
    db.collection("Teams").doc(doc.id)
      .update({
        teamMembers: firebase.firestore.FieldValue.arrayUnion({
          // team member info
        })
      })
  });
})

let ref = db.collection("Teams").doc(this.$route.params.id);
ref.update({
  teamMembers: firebase.firestore.FieldValue.arrayUnion({
    // team member info
  })
})      

正如所料,这两种方式都没有达到我想要的程度。

我如何尝试检索信息:通过Firestore控制数据的整体结构,我尝试了以下方法来获得与相同的结果:to=“{name:'PageThatShowsTeamMembers',params:{id:id,data:teamMemberData}}以前的方法无效。

let ref = db.collection("Teams").where("userId", "==", this.$route.params.id)
ref
  .get()
  .then(querySnapshot => {
    querySnapshot.forEach(doc => {
      this.members.push(...doc.data().teamMembers)
    });
  })
  .catch(err => {
    console.log(err);
  })

上面的代码块获取与路由参数中的id(即当前用户uid)关联的每个团队。这不是期望的结果,因为所有成员都将为每个团队显示,而不是为任何单击的团队显示特定的成员。

let ref = db.collection("Teams").doc(this.$route.params.id).collection("Team Members")

ref.get().then((querySnapshot) => {
  querySnapshot.forEach((doc) => {
    this.members.push(doc.data());
  });
});

这个代码块提供的结果更接近于:to=“{name:'PageThatShowsTeamMembers',params:{id:id,data:teamMemberData}}方式,但由于该数据要求在添加新团队成员时使用set()方法,而不是add()method,我觉得我的文档大小很快就会达到1mb的限制,而且当我需要另一个页面时,我无法轻松地查询集合中所有团队成员的列表。

事情现在在哪里:这把我带到了目前的情况。我已经广泛地研究了我可以开始在FiRecovery中重构数据的方法。我已经通读了以下帖子:Firebase中的多对多关系Firebase Cloud Firepository中的多对多关系Firebase查询孩子的孩子是否包含一个值以及除此之外的许多其他值,我仍然对如何为团队成员存储uid感到困惑一个特定的团队只得到我想要的特定数据。我在一些建议答案的帖子中看到,uid存储为要检索的字段键,但我不知道一旦我查询它们,它将如何列出数据。我也越来越怀疑将团队成员信息本身存储在数组或地图字段中,因为这些数据本身由7个以上的字段组成。

在观看了Firebase讨论数据建模和非规范化的视频并对其进行了更多思考后,我有了一个想法,那就是让团队成员拥有自己的顶级集合,并可能以某种方式存储任何一名成员所属团队的名称,但我不确定这是团队成员的文档id还是我查询的文档中的字段。除此之外,我对在Vue中如何使用路由感到困惑。如果我让团队命名文档id,我将如何在路由器链接中正确设置它,以获得我想要的结果。另一种选择是将团队成员设置为子集合,但随后我会失去一些查询功能,并增加必须进行的读取次数。

我知道没有一种特定的“正确”的方式来处理它,而且无论如何都会有折衷,我只是想更清楚地了解代码的实际外观。我还想知道使用当前用户uid作为用户集合之外的任何内容的文档id是否合理?我最初的想法是团队属于特定的用户,但路上的这些坎坷让我重新思考我的方法。

我想运行的查询示例:

let ref = db.collection("Team Members").where("teamId", "==", this.$route.params.id) // the id here could possibly be the team name or the document id or something along those lines
ref
  .get()
  .then(querySnapshot => {
    querySnapshot.forEach(doc => {
      this.members.push(doc.data())
    });
  })
  .catch(err => {
    console.log(err);
  })

根据Ernesto的评论,我写了一个我想写的示例查询,源于拥有顶级团队成员集合的想法,该集合跟踪该成员所在的团队。我的想法是,对于这样的查询,路由参数中的id可能是团队名称或团队成员当前所在团队集合中的文档id。对于这种方法,我唯一的犹豫是如何在vue的数据道具中正确设置id。

共有1个答案

慕弘深
2023-03-14

基于本文,我制作了一个简单的Firestore数据库,其结构如下:

TeamMembers (Collection)
    tm1 (Doc)
        “FullName”: “John Smith”,
        “MemberOf”: [“team1”, “team2”]
    ...

Teams (Collection)
    team1 (Doc)
        “Owner”: “tm1”,
        “Members”: [“tm1”, “tm2”, tm3”]
    ...

在这个用例中,一个团队可以有多个成员,并且每个成员都可以是多个团队(M:N)的一部分,这是可行的。正如你在问题中所说,这里可以采取多种方法。数组成员文档中包含了用于查询此结构的有用运算符。例如,下面的查询将为我提供属于“team1”的所有团队成员:

  let teamRef = firestoreDB.collection("TeamMembers").where("MemberOf", "array-contains", "team1");
  teamRef.get()
    .then((qSnap) => {
      qSnap.forEach((doc) => {
        console.log(doc.data().FullName);
      });
    })
    .catch((err) => {
      console.log("Caught error: ", err);
    });

我们可以编辑此查询以相反的方式工作,查找团队成员所属的团队:

  let teamRef = firestoreDB.collection("Teams").where("Members", "array-contains", "tm1");
  teamRef.get()
    .then((qSnap) => {
      qSnap.forEach((doc) => {
        console.log(doc.id); // Since the team name is the doc ID, it can be obtained from the DocumentSnapshot object
      });
    })
    .catch((err) => {
      console.log("Caught error: ", err);
    });

必须使用批写入来执行添加或删除操作,这样才能在无法完成一半的原子操作中更新团队和团队成员文档的相关数组。至于如何获取与Vuejs数据道具一起使用的文档ID,我找到了这个相关问题和Vuejs的相关参考资料。

 类似资料:
  • 问题内容: 我有以下实体关系问题。一个“游戏”必须有两个(只有两个)“团队”对象。一个“团队”可以有很多“游戏” 据我所知,这是一对多关系。但是…我不知道如何在JPA中对此建模。例如,我打算做这样的事情… 但是,正如您所看到的,我不确定如何从注释侧将表链接在一起。有人曾经做过这样的事情吗?有什么想法吗? 非常感谢! 问题答案: 我希望有人能提出一个很棒的解决方案,但是这是一个棘手的情况,我从未能找

  • 问题内容: 在关系数据库中,我有一个用户表,一个类别表和一个用户类别表,它们之间存在多对多关系。在Redis中具有这种结构的更好形式是什么? 问题答案: 使用Redis,关系通常由集合表示。一组可用于表示单向关系,因此每个对象需要一组以表示多对多关系。 尝试将关系数据库模型与Redis数据结构进行比较是毫无用处的。使用Redis,所有内容均以非规范化方式存储。 例: 一旦有了此数据结构,就可以使用

  • 我想创建一个如下所示的数据库。我阅读了文档,但没有找到任何类似的例子。你能帮助我吗?有几天,在这几天内,每天将有多顿饭和每天的地下水位 一旦应用程序启动,就会创建一个日期数据库,然后无论它在哪一天(可以手动更改日期),都会将每日水和每日膳食添加到那一天

  • 我需要创建一个学生管理系统,它可以帮助多个老师教多个学生,多个学生可以有多个老师。现在我已经在下面创建了一个代码。另外,如果你认为有更好的方法来实现我的目标,请指导,我对多对多的关系是新的,互联网上有这么多方法,这只是让人困惑: 错误是:

  • 问题内容: 我具有实现的接口层次结构。我想使用不可变的对象,所以我想设计一些类来方便地构造这些对象。但是,我有很多接口,并且我不想在每种类型的子生成器中重复构建s 的代码。 因此,假设以下定义: 我怎样才能有效地实施的建设者和?他们应支持以下操作: 和 我不想为每个子生成器实现一个特殊情况。 编辑以添加第二个属性,以澄清使用简单的泛型无法做到这一点。我不是在寻找一种方式来组合和-我正在寻找一种方式

  • 所以我试图从数据库模型创建一个EER图,我想做类似的事情。 我想知道是什么导致了这种情况的发生(也许我做错了什么,但现在我想不出任何合理的解释…) 希望有人能对此有所启发。 谢谢!