firebase 如何构建Cloud Firestore中所有用户的通用数据?

nx7onnlm  于 2023-05-01  发布在  其他
关注(0)|答案(1)|浏览(125)

我正在开发一个类似Goodreads的应用程序,并使用Cloud Firestore作为后端。我目前的DB结构是这样的:

Users (collection)
    uniqueUser1 (document)
        user1Metadata (fields)
        ...
        books (sub-collection)
            book1 (document)
                globalBook1Metadata (fields such as genre, year published, etc)
                ...
                user1Book1Metadata (fields such as rating, comments, date added, etc)
            book2 (document)
                globalBook2Metadata (fields such as genre, year published, etc)
                ...
                user1Book2Metadata (fields such as rating, comments, date added, etc)
    uniqueUser2 (document)
        ...
        books (sub-collection)
            book2 (document)
                globalBook2Metadata (fields such as genre, year published, etc)
                ...
                user2Book2Metadata (fields such as rating, comments, date added, etc)
            book3 (document)
                ...

我有一个包含用户文档的用户集合。每个用户文档都包含一些唯一的用户元数据沿着书籍的子集合。子集合中的每本书都有一些对用户来说唯一的全局元数据和数据。
这在存储方面似乎非常低效。每次用户添加图书时,我都会存储全局图书元数据。在上面的例子中,book 2被存储了两次。所以我的下一个想法是在根级别添加一个图书集合,如下所示:

Books (collection)
    book1 (document)
        globalBook1Metadata (fields such as genre, year published, etc)
    book2 (document)
        globalBook2Metadata (fields such as genre, year published, etc)
    book3 (document)

这在存储方面更好。我现在只需要将图书ID存储在用户文档中,然后查询这个集合来获取全局图书元数据。
但现在有一个新问题。假设我想根据流派过滤用户的库。好吧,因为流派只存储在Books集合中,所以我必须从Books集合中获取与用户的图书子集合中的id相匹配的所有图书。这有可能是非常大量的读取,这是昂贵的。
所以我的问题可以归结为两个部分:
1.有没有一种方法可以发送一个查询,从Books中获取所有与用户的图书子集合具有匹配id的图书?如果是这样,那将是一个很好的解决方案。
1.如果没有,什么是最好的方法来组织这些数据,这样我就不会做过多的R/W或使用太多的存储方式?
我是一个前端开发人员,所以这对我来说是一个新的领域。先谢谢你了!

bjg7j2ky

bjg7j2ky1#

您使用第二种方法是一个很好的方法,第一种方法仍然可以工作,但不可扩展。
如果你想保持当前的结构,你有:

  • 藏书
    -- document_id1
    -- document_id2
    你可以通过在每个用户中拥有书籍的UID数组来实现不错的结果(你可以使用ArrayUnion和ArrayRemove添加和删除它们),然后你可以根据用户从过滤器中选择的流派和保存的UID书籍数组进行查询,并使用 “in” 操作符,它看起来像这样:
const q = query(collection(db, "books"), where('genre', '==', 'comedy'), where('bookIdField', 'in', user.uidArrayFavBooks));

通过这种方式,您将只通过一个查询获得所需的结果。
如果你想稍微优化它,你可以将用户文档中的通用UID数组分离到不同的流派数组,如果你知道100%的所有流派输入,比如:

comedy: ['id1', 'id2']
action: ['id1', 'id3', 'id6']
...and so on

***注意:*如果流派选项不由您控制,我不会建议您这样做,因为依赖用户数据输入的预测不是好的做法。

作为一种解决方法,您可以将具有UID和流派的对象存储在数组中,并将其传递给具有所选流派的过滤器方法的查询,例如:

const userFavBooks = [
    { id: 1, genre: "drama" },
    { id: 2, genre: "action" },
    { id: 3, genre: "comedy" },
    { id: 4, genre: "drama" },
  ];
const filteredBooksArray = userFavBooks.filter((e) => e.genre === "drama").map((e) => e.id) // [1,4]

const q = query(collection(db, "books"), where('bookIdField', 'in', filteredBooksArray));

相关问题