何时在NoSQL中复制数据?

4
我正在处理一个使用Firebase Firestore的项目。我没有使用过noSQL,所以我正在努力理解这项技术。
该应用程序允许用户选择电影类别并下载相关电影进行编辑。类别和电影不会被用户更改,将由所有者固定或更改。可以将其看作是类似Netflix目录,用户只能观看电影。
有几个类别,但目前只有一个类别中有一个电影(稍后可能会有更多)。每部电影都有相关元数据。
未来: - 将使用用户对象根据他们的得分(与应用程序相关的信息)对每个用户进行排名。 - 某些电影将根据本地化限制可用,即仅美国用户可以观看某部电影。
在我的第一次想法中,数据结构将如下所示:
// Collection
Category: {
    name: "drama" // Could be action, or other
}

// Collection
Movie: {
    name: "Matrix"
    description: "Best movie ever"
    duration: 1321312
    url: "https://www....."
    allowedCountry: "us" // is it the right place for this field?
    category: "drama" // is it ok to duplicate data here?
}

//Collection
user: {
    ranking: 3
    withMovie: "Matrix" // is it ok to duplicate data here?
}

我不确定这是否是适合此问题的正确数据结构。

应用程序的流程将首先呈现所有可能的类别(因此我创建了一个单独的集合,以避免迭代所有歌曲以获取类别)。

然后当用户选择一个类别时,可能的电影会显示出来,应用程序会下载所选电影。

在显示与类别相关的电影时,是否可以迭代所有可能的电影?还是应该将电影作为类别集合的子集合?


回答你的问题,数据可以尽可能地重复。NoSQL替代了SQL的原因是硬件成本——存储曾经是数据库中最昂贵的组成部分,现在则是最便宜的(现在最昂贵的组成部分是CPU)。复制数据的成本(称为反规范化/反规范化)只有很少的投入。与NoSQL相关的费用,如Firebase和Firestore,几乎全部来自于查询(Firebase强调数据量,Firestore强调文档数量)。 - trndjc
尽可能地去反规范化你的数据,以减少查询占用的空间。也就是说,如果你需要将一个字段重复n次以将查询缩减到单个调用、单个文档或者仅仅是不过度查询(获取比你需要的结果更多),那么请毫不犹豫地这样做。 - trndjc
1个回答

1
在这种情况下,我通常会将类别直接保留在电影文档中,因为这样查询就更容易阅读。
firebase.firestore().collection("movies").where("category", "==", "drama")

事实上,考虑一下你的电影是否真的只能有一个类别(就像你现在建模的那样),或者它们将来是否可能有多个类别(就像我所知道的 Netflix 一样)。你可以将后者建模为类别数组:
categories: ["drama", "sci-fi"]

然后使用以下内容进行查询:
firebase.firestore().collection("movies").where("categories", "array-contains", "drama")

感谢您的帮助。因此,我将保留“Category”集合以显示可用类别,并将它们复制到“Movie”集合中。另一个愚蠢的问题,像这样查询可以吗?我的意思是遍历所有电影不是很慢吗?我不知道NoSQL性能,所以我想知道它的表现如何。 对于“用户”排名也是同样的情况,如果我们有100,000个用户,按顺序显示全球排名不会很慢吗? - DEADBEEF
对我来说,categories 数组中的值在关系模型中相当于外键。关于性能的问题:Firestore 在这方面非常独特。它的查询 API 相当有限,但它通过具有独特的性能保证来弥补这一点:查询性能不取决于您查询的文档数量,而仅取决于您请求的文档数量。 - Frank van Puffelen

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