我正在尝试构建一个约会应用程序,对于我的后端,我使用的是 nosql 数据库。当涉及到用户的集合时,同一集合的文档之间会发生一些关系。例如,用户 A 可以喜欢、不喜欢,或者可能还没有选择。此场景的简单架构如下:
database = {
"users": {
"UserA": {
"_id": "jhas-d01j-ka23-909a",
"name": "userA",
"geo": {
"lat": "",
"log": "",
"perimeter": ""
},
"session": {
"lat": "",
"log": ""
},
"users_accepted": [
"j2jl-564s-po8a-oej2",
"soo2-ap23-d003-dkk2"
],
"users_rejected": [
"jdhs-54sd-sdio-iuiu",
"mbb0-12md-fl23-sdm2",
],
},
"UserB": {...},
"UserC": {...},
"UserD": {...},
"UserE": {...},
"UserF": {...},
"UserG": {...},
},
}
这里 userA 有一个来自它所见过并做出决定的用户的参考,并将它们存储在“users_accepted”或“users_rejected”中。如果用户 A 没有见过用户 C(喜欢或不喜欢),那么很明显它不会出现在两个数组中。但是,这些数组是无界的,并且可能超出文档可以处理的最大大小。其中一种方法可能是提取这两个数组并创建以下模式:
database = {
"users": {
"UserA": {
"_id": "jhas-d01j-ka23-909a",
"name": "userA",
"geo": {
"lat": "",
"log": "",
"perimeter": ""
},
"session": {
"lat": "",
"log": ""
},
},
"UserB": {...},
"UserC": {...},
"UserD": {...},
"UserE": {...},
"UserF": {...},
"UserG": {...},
},
"likes": {
"id_27-82" : {
"user_give_like" : "userB",
"user_receive_like" : "userA"
},
"id_27-83" : {
"user_give_like" : "userA",
"user_receive_like" : "userC"
},
},
"dislikes": {
"id_23-82" : {
"user_give_dislike" : "userA",
"user_receive_dislike" : "userD"
},
"id_23-83" : {
"user_give_dislike" : "userA",
"user_receive_dislike" : "userE"
},
}
}
我需要 4 个基本查询
查询1.相当简单,只需查询likes集合并获取“user_receive_like”为“userA”的用户即可。
查询2.和3.用于获取userA尚未见过的用户,获取不在查询2.或查询3.中的用户
最后查询4.可能是另一个集合
"matches": {
"match_id_1": {
"user_1": "referece_user1",
"user_2": "referece_user2"
},
"match_id_2": {
"user_1": "referece_user3",
"user_2": "referece_user4"
}
}
这种方法可行且有效吗?
您注意到了,这些数组是无界的,会给您的应用程序带来严重的可扩展性问题。如果您要使用第一种方法为用户分配 2-3 个用户角色,那完全没问题,但您的情况并非如此。 MongoDB 官方文档建议您不应使用无界数组:https://www.mongodb.com/docs/atlas/schema-suggestions/avoid-unbounded-arrays/
您的第二种方法是您的最佳实施选择,因为:
(user_give_dislike, user_receive_like)
形式的索引,即使您有 1M+ 文档,这也将提高您的查询性能likes
集合上存储其他元数据(如时间戳等),而不会影响用户集合的设计有关 NoSQL 数据建模的更多信息: https://www.mongodb.com/docs/manual/data-modeling/ 和 https://www.mongodb.com/docs/manual/tutorial/model-referenced-one-to-many-relationships- Between-documents/
为了回答您的问题,让我写一些有关该域的更多假设,然后让我们尝试回答它。
假设:
还有一些关于 nosql 的理论,如果我们的查询转到集合的所有分片,那么系统的最大规模取决于单个分片的规模
现在有了这些假设,看看您提出的问题的查询性能:
假设我们正在进行分片或 user_give_like 列,那么如果我们对 user_receive_like 进行过滤那么它将对所有分片进行查询,这对于可扩展性来说不是正确的事情
获取UserA点赞的用户 这将工作得很好,因为我们已经基于 user_give_like 创建了分片
获取UserA不喜欢的用户 这会很好地工作,因为我们已经根据 user_give_dislike 创建了分片
获取UserA拥有的匹配项 在这种情况下,如果我们在现有用户和 UserA 喜欢和不喜欢的所有用户之间进行连接,这将在所有分片上创建并行查询,并且当 UserA 喜欢或不喜欢的数量巨大时,该查询不可扩展
现在得出结论,这对我来说似乎不是一个合理的方法。
您为约会应用程序后端使用 NoSQL 数据库的想法很有意义,特别是在同一集合中的用户之间存在动态且通常复杂的关系的情况下。数组提取确实是一种可行的方法,因为它允许有效查询和管理用户交互(例如喜欢和不喜欢)。