将类似Instagram的关系型数据库转换为Firebase NoSQL

8

我计划开发生产就绪的混合ionic3移动应用程序,类似于使用firebase的instagram. 我选择使用Firestore nosql来存储数据和查询。

我有在RDMS中设计模式的经验(忽略第二个绿色用户表)。但我在设计NoSql架构方面遇到了困难。下面我添加了我想要将其转换为nosql的RDMS架构。

rdms table schema

我想要有效地进行多种查询。

  1. 显示客人会话主页上最新照片列表。
  2. 显示用户关注者的照片列表。
  3. 列出由“标记”标记的照片。

上面列表的简单Sql查询

  1. Select * from photo LIMIT=50

为了有效地进行查询,我该如何将photouser表转换为firestore NoSql或NoSql?


这个 NoSql 语言中是否有 ORDER BY 子句(针对项目1)?UNION(针对项目2)?JOIN(针对项目3)?如果没有,那么为什么要远离关系型数据库管理系统? - Rick James
@RickJames 因为 Firebase 只支持 NoSQL 数据库,而我想将其作为我的移动应用后端。它支持 order by,但不支持 joinsunions - omurbek
问题在于我无法像 SQL 一样进行 连接嵌套查询。由于 Firebase 正在不断发展,他们计划支持诸如 in 等子句。 - omurbek
我不明白。你想要“查询效率”,但是你却要迁移到一个性能较弱的平台? - Rick James
它有许多好处,自动缩放,实时性,身份验证,监控应用程序,缺点是“较少的从句”。 - omurbek
显示剩余2条评论
2个回答

4

这里有一个提案:

一个名为photos的集合

其中包含具有以下内容的photo文档:

  • 自动生成的Id
  • 一个保存日期(即时间戳)的creation字段
  • 额外的字段,例如描述、url/path等
  • 一个tags字段作为一个对象,带有键值对,如{black: true, cats: true},请参阅此帮助文档以了解其原理:https://firebase.google.com/docs/firestore/solutions/arrays。下面的HTML代码显示了如何使用/查询它
  • comments的子集合

一个名为users的集合

其中包含具有以下内容的user文档:

  • 用户的ID(即来自身份验证的uid
  • 一个followedUsers对象,保存当前用户关注的用户ID {userId1: true, userId2: true}
  • 一个followedPhotosId对象,保存当前用户关注的照片ID {9HzWzyXmcnBDuhTZKoQw: true, fO0OvzJs9M8p9N0jufte: true}
  • 一个followedPhotos子集合,保存关注的照片的详细信息

以下HTML页面展示了如何执行您在帖子中列出的查询,以及一些读写数据的查询:这些最新的查询应该用于几个云函数,专门用于在用户关注新用户和/或被一个或多个用户关注的用户添加或删除照片时保持followedPhotosId对象和followedPhotos集合同步。

<html>

<head>

<!-- Firebase App is always required and must be first -->
<script src="https://www.gstatic.com/firebasejs/5.3.0/firebase-app.js"></script>

<!-- Add additional services that you want to use -->
<script src="https://www.gstatic.com/firebasejs/5.3.0/firebase-auth.js"></script>
<script src="https://www.gstatic.com/firebasejs/5.3.0/firebase-database.js"></script>
<script src="https://www.gstatic.com/firebasejs/5.3.0/firebase-firestore.js"></script>
<script src="https://www.gstatic.com/firebasejs/5.3.0/firebase-functions.js"></script>


</head>

<body>


<script>
  // Initialize Firebase
  var config = {
    apiKey: "",
    authDomain: "xxxxx.firebaseapp.com",
    databaseURL: "https://xxxx.firebaseio.com",
    projectId: "xxxxxx"
  };

  firebase.initializeApp(config);

  var firestoredb = firebase.firestore();


  firestoredb.collection("photos").orderBy("creation", "desc")
    .get()
    .then(function(querySnapshot) {
        console.log("YOUR QUERY #1");
        querySnapshot.forEach(function(doc) {
            // doc.data() is never undefined for query doc snapshots
            console.log(doc.id, " => ", doc.data());
        });
    })
    .catch(function(error) {
        console.log("Error getting documents: ", error);
    });


  firestoredb.collection("users").doc("user1").collection("followedPhotos")
    .get()
    .then(function(querySnapshot) {
        console.log("YOUR QUERY #2");
        querySnapshot.forEach(function(doc) {
            // doc.data() is never undefined for query doc snapshots
            console.log(doc.id, " => ", doc.data());
        });
    })
    .catch(function(error) {
        console.log("Error getting documents: ", error);
    });


  firestoredb.collection("photos")
    .where('tags.cats', '==', true) //You should create a photo with a "cats" tag
    .get()
    .then(function(querySnapshot) {
        console.log("YOUR QUERY #3");
        querySnapshot.forEach(function(doc) {
            // doc.data() is never undefined for query doc snapshots
            console.log(doc.id, " => ", doc.data());
        });
    })
    .catch(function(error) {
        console.log("Error getting documents: ", error);
    });




  firestoredb.collection("photos").orderBy("creation", "desc").limit(50)
    .get()
    .then(function(querySnapshot) {
        console.log("YOUR QUERY #4, i.e; Select * from photo LIMIT=50");
        querySnapshot.forEach(function(doc) {
            // doc.data() is never undefined for query doc snapshots
            console.log(doc.id, " => ", doc.data());
        });
    })
    .catch(function(error) {
        console.log("Error getting documents: ", error);
    });

  firestoredb.collection("users")
   .where('followedUsers.user2', '==', true)
   .get()
   .then(function(querySnapshot) {
      console.log("Get all the users who follows user2. To use in the Cloud Function");
      querySnapshot.forEach(function(doc) {
        // doc.data() is never undefined for query doc snapshots
          console.log(doc.id, " => ", doc.data());
      });
  })
  .catch(function(error) {
      console.log("Error getting documents: ", error);
  });


   firestoredb.collection("users")
    .where('followedPhotosId.9HzWzyXmcnBDuhTZKoQw', '==', true)
    .get()
    .then(function(querySnapshot) {
        console.log("Get all the users who follow photo with Id 9HzWzyXmcnBDuhTZKoQw. To use in the Cloud Function");
        querySnapshot.forEach(function(doc) {
            // doc.data() is never undefined for query doc snapshots
            console.log(doc.id, " => ", doc.data());
        });
    })
    .catch(function(error) {
        console.log("Error getting documents: ", error);
    });


    firestoredb.collection("users").doc("user1").get().then(function(doc) {
      if (doc.exists) {
          console.log("Update the followedPhotosId object for user1 after a user she/he follows has added a photo with id abcdefghijklmn. To use in the Cloud Function");
          var followedPhotosId = doc.data().followedPhotosId;;
          Object.assign(followedPhotosId, {abcdefghijklmn: true});
      firestoredb.collection("users").doc("user1").set({followedPhotosId: followedPhotosId});
      } else {
        // doc.data() will be undefined in this case
        console.log("No such document!");
      }
    }).catch(function(error) {
      console.log("Error getting document:", error);
    });




</script>


<body>
</html>

1

这里是Firestore的指南,可以帮助你设计数据模型。此外,你需要考虑信息如何被访问,以便查询尽可能扁平(因为NoSQL中不应该有连接操作)。

例如,如果你需要一个显示用户信息和照片的屏幕,请创建一个名为User的集合,并在其中添加子集合Photo。如果你需要一个用户照片列表,则创建一个单独的Photo集合。

我建议你遵循非规范化的方式来处理相关数据,但要小心,因为这可能很难维护。

作为最后的建议(也是个人意见),你需要放弃你的SQL知识,停止思考数据之间的关系,然后考虑如何以适合你的应用程序的方式访问信息,并利用Firestore索引


1
你能为你的例子添加插图吗? - omurbek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接