如何在NoSQL环境中创建以下数据结构

4

介绍
我有一个与社交媒体类似的FireStore数据库,包括三个集合:用户,事件和事件更新。我的目标是创建一个由我和我的朋友创建的事件更新的动态。因此,我需要通过扩展我的数据库建立友谊关系连接。但我遇到了三个问题,希望这里的某个人可以指导我解决这些问题。

问题/疑问1:
我将用户名和用户图像添加到了EventUpdate模型中,以便更轻松地查询。我听说denormalise是在NoSQL数据库中要去走的路线。但如果用户更新了他的用户图像,则我必须更新该用户创建的所有事件更新。这听起来像是你不想做的事情。但是否有更好的方法来解决这个问题?

问题/疑问2:
如何创建一个针对执行以下查询进行优化的数据结构:按日期获取由我和我的朋友发布的事件更新。

问题/疑问3:
如何存储点赞?我可以在一个eventUpdate中保留一个计数器。但当我denormalise eventUpdates时(请参见EDIT下面的当前解决方案),这将成为一个问题。

数据结构示例

{
  "users": {
    "1": { "name": "Jack", "imageUrl": "http://lorempixel.nl" }
  },
  "events": {
    "A": { 
      "name": "BeerFestival", 
      "date": "2018/09/05",
      "creatorId": "1"
    }
  },
  "eventUpdates": {
    "1": {
      "timestamp": "13243543",
      "creatorId: "1",
      "creatorName": "Jack",
      "creatorImageUrl": "http://lorempixel.nl",
      "eventId": "A",
      "message": "Lorem ipsum"
    }
  }
}

编辑

好的,在进行了一些试验和错误之后,我最终采用了以下结构。这种结构似乎是有效的,但我的问题在于,由于每个订阅源中都有副本(1000个关注者意味着1000个副本),因此我需要进行大量的写操作来更新单个事件更新。而且看起来我需要经常这样做。

例如,我想为每个事件更新添加一个"喜欢"按钮。这会触发对所有EventUpdate副本的更新。对我来说,Firebase似乎不适合我的项目,我正在考虑用SQL数据库替换它,或者这里有谁可以提供更好的解决方案?

{
  "users": {
    "user1": { "name": "Jack", 
      "imageUrl": "http://lorempixel.nl",
      "followers": ["user1"]
    }
  },
  "feeds": {
    "user1": {
      "eventUpdates": {
        "1": {
          "timestamp": "13243543",
          "creatorId: "1",
          "eventId": "A",
          "message": "Lorem ipsum"
        }
      },
      "following": {
        "user1": { 
          "name": "Jack", 
          "imageUrl": "http://lorempixel.nl",
          "followers": ["user1"]
        }
      }
  },
  "events": {
    "A": { 
      "name": "BeerFestival", 
      "date": "2018/09/05",
      "creatorId": "1"
    }
  }
}

在Firestore中,您可以将引用用作字段值。当您进行去规范化时,请使用引用指向可能会更改的内容。如果它不能或不应更改,则使用值。接下来,您需要异步加载消息。首先,检索消息列表,然后解析引用。根据您使用的技术,有许多选项,但基本上只需运行第二个查询即可。Firestore将在设备上缓存结果,因此对同一文档的后续查询将仅返回缓存。 - James Poag
3个回答

4
我在EventUpdate模型中添加了用户名和用户图像,以便更轻松地查询。我听说在NoSQL数据库中,去规范化是一种可行的方法。
没错,去规范化在Firebase中是常见的做法。如果您是NoSQL数据库的新手,我建议您观看这个视频Denormalization is normal with the Firebase Database以获得更好的理解。它是针对Firebase实时数据库的,但同样适用于Cloud Firestore。
但是,如果用户更新了其用户图像,则必须更新该用户创建的所有eventUpdates。听起来不是很理想。但有没有更好的方法呢?

是的,那也是正确的。您需要更新所有存在该图像的地方。因为您选择了google-cloud-firestore作为标签,我建议您查看我的答案来自这里的post,因为在进行许多写操作的情况下,Firestore可能有点昂贵。请还要参见Firestore pricing plans

关于Firestore,您只能保存对图片的引用,而不是整个对象。在这种情况下,没有什么需要更新的。这总是这两种技术之间的权衡,不幸的是没有其他方法。您可以保存对象或仅保存对对象的引用。对此,请参见我的答案来自这里的post

如何创建一个针对执行以下查询进行优化的数据结构:按日期获取我和我的朋友的事件更新。

据我所见,你的模式更像是Firebase实时数据库模式而不是Cloud Firestore。回答你的问题,是的,你可以创建。关于Firestore,你可以创建一个名为eventUpdates的集合,它可以容纳eventUpdate对象,并根据时间戳查询它,需要这样的查询:
FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
CollectionReference eventUpdatesRef = rootRef.collection("eventUpdates");
Query query = eventUpdatesRef.orderBy("timestamp", Query.Direction.ASCENDING);

但请注意,timestamp字段应该是Date类型而不是long。另外,请查看我在这个post中的答案,了解如何在Cloud Firestore数据库中添加日期属性。

如何存储赞?我可以在eventUpdate中保留一个计数器。但是当我去规范化eventUpdates时(请参见EDIT下面的当前解决方案),这会成为一个问题。

您可以简单地添加赞,但我建议您查看我在此post的答案的最后一部分。因此,您可能需要将该计数添加到Firebase实时数据库中,而不是Cloud Firestore中。这两个数据库非常好配合使用。

这个结构似乎可行,但我对这种解决方案的问题在于,由于每个订阅源中都有副本(1000个关注者意味着1000个副本),我需要做很多写调用来更新单个 eventUpdate。而且看起来我需要经常这样做。
你还可以查看我的答案,来自这个post
对我来说,Firebase 不适合我的项目,我正在考虑用 SQL DB 替换它,或者有人能够提供更好的解决方案来改变我的想法吗?
我不认为这样做是正确的。有很多应用程序与您的完全相同的机制,并且运行良好。

嗨,Luciano!我能帮你提供其他信息吗? - Alex Mamo
谢谢,这是非常有帮助的信息。我已经想好了如何重构我的结构,但仍需要实施并观察其性能。 - Luciano
1
不客气,Luciano!如果你有任何其他问题,请发布另一个问题,这样我或其他Firebase开发人员可以帮助你。干杯! - Alex Mamo

0
如果你希望你的动态项目与真实用户数据同步(例如,当用户更改新的个人资料图片时),你可以简单地将用户ID存储在eventUpdate文档中。这样,你就不必手动保持它们同步,每次需要在动态中显示项目时,你只需获取用户数据,并且可以轻松地根据userIdcreated_at字段查询多个eventUpdate
要在你的动态中实现点赞功能,解决方案取决于一系列因素,如流量大小。 最简单的方法是使用事务更新一个likes字段,但Firestore对单个文档的最大更新频率为1秒。此外,如果有超过5个事务尝试更新同一文档,事务很容易失败。
要实现更可靠的likes系统,请参考官方Firebase文档中的this page

0

Firestore 对 NoSQL 世界有不同的方法。一旦您知道将要使用的数据(就像您已经知道的那样),关于数据将具有什么体系结构有一些非常重要的要点。这在很大程度上取决于数据的增长方式、您需要什么类型的查询以及您将多频繁地使用它们。在某些情况下,您可以创建一个根集合来聚合数据,查询可能会更容易。

来自 Firebase 频道的一段极好的视频可能会有所帮助。看看它吧! 如何构建数据结构 | 认识 Cloud Firestore #5 https://www.youtube.com/watch?v=haMOUb3KVSo

[更新] 12月26日

其他可以帮助您建模和查询数据的视频包括:

如何将 Firebase 用户连接到他们的数据-3 种方法 https://www.youtube.com/watch?v=jm66TSlVtcc

如何避免获得30K Firebase账单 https://www.youtube.com/watch?v=Lb-Pnytoi-8

在Firestore NoSQL中建模关系数据 https://www.youtube.com/watch?v=jm66TSlVtcc


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