首页 > 解决方案 > 在 node.js 中戳其他用户模式的用户模式

问题描述

我正在制作一个用户可以戳其他用户的应用程序。这是我考虑过的模式设计的代码。第一个是只使用一个users模式:

const userSchema = new Schema({ 
  name: { type : String},
  pokes: [{ type : Schema.Types.ObjectId, ref: 'Users' ,default:null}],
});

另一种方法是使用pokes模式。在这里,我将模式的对象存储在模式ids中。pokesusers

const pokesSchema = new Schema({ 
  from_user_id: { type : Schema.Types.ObjectId, ref: 'Users' ,default:null},
  to_user_id: { type : Schema.Types.ObjectId, ref: 'Users' ,default:null},
});

const userSchema = new Schema({ 
  name: { type : String},
  pokes: [{ type : Schema.Types.ObjectId, ref: 'Pokes' ,default:null}],
});

在第三种方式中,我完全删除了两个模式之间的关系:

const pokesSchema = new Schema({ 
  from_user_id: { type : Schema.Types.ObjectId, ref: 'Users' ,default:null},
  to_user_id: { type : Schema.Types.ObjectId, ref: 'Users' ,default:null},
});

const userSchema = new Schema({ 
  name: { type : String},
});

在第二种和第三种方式中,我可以轻松查询戳。我想知道这三个中哪一个是最好的设计以及为什么。另外,如果userAuserB的话,userB也可以戳回来userA。我node.js目前正在学习,对mongoDb.

标签: javascriptnode.jsmongodb

解决方案


好的,所以这是我能做的最好的。您在上面的评论中简要回答了我的问题,但我想指出重要的是要考虑您正在做什么(或期望做什么)更多以及更多。尽管如此,让我们来看看每个模式。

const userSchema = new Schema({ 
    name: { type : String},
    pokes: [{ type : Schema.Types.ObjectId, ref: 'Users' ,default:null}],
});

当我们查看第一个时,它似乎不足以满足您的需求。它是一组用户,他们有一个名字和他们所做的一系列戳。如果我们需要知道用户戳了谁,那么这是一个非常简单快速的查询 - 它就在他们的名字下,按nameor搜索_id,我们就完成了!但是当你想查找谁戳了这个用户时会发生什么?您将需要查询每个用户,然后在每个 pokes 数组中搜索原始用户。如果我们有 m 个用户并且每个用户有 n 个 poke,那就是在进行 m*n 测试。哎呀。如果 m 和 n 变大,那将是很多(想想 100 * 100 与 10,000 * 10,000 甚至更多的差异!)。即使您个人没有在您的节点中对该搜索进行编码,那么 mongo 也会进行该搜索。因此,除非您确定查找谁戳过用户将是非常罕见的事情,否则这可能不是一个好的选择。继续:

const pokesSchema = new Schema({ 
    from_user_id: { type : Schema.Types.ObjectId, ref: 'Users' ,default:null},
    to_user_id: { type : Schema.Types.ObjectId, ref: 'Users' ,default:null},
});

const userSchema = new Schema({ 
    name: { type : String},
    pokes: [{ type : Schema.Types.ObjectId, ref: 'Pokes' ,default:null}],
});

现在我们有了一个 pokes 模式,很好!如果我们想进行上面讨论的搜索,我们可以直接基于查询 pokes to_user_id,然后如果我们需要所有发起 pokes 的用户的名称,我们可以根据它查询用户_id。不错!我们仍然有快速的方法来获得相反的结果,也就是搜索用户发起的戳,因为pokes我们的用户模式中仍然存在。但是,当 poke 发生时会发生什么?我们必须更新两个模式。所以我们不仅要做一个(相对容易的)插入到戳中,我们还必须更新我们的戳用户的戳数组。这可能不是那么糟糕,但如果一次更新失败会发生什么?现在我们的数据不一致- 用户和戳不匹配。每次戳我们都会将更新翻倍。这可能没什么大不了的,如果我们得到用户的戳比我们戳的多,那么这可能是一个不错的权衡,但它变得有点风险,因为我们已经引入了一些我们可能不一致的地方. 好的,最后一个:

const pokesSchema = new Schema({ 
    from_user_id: { type : Schema.Types.ObjectId, ref: 'Users' ,default:null},
    to_user_id: { type : Schema.Types.ObjectId, ref: 'Users' ,default:null},
});

const userSchema = new Schema({ 
  name: { type : String},
});

首先,请注意这些模式仍然是相关的 - poke 模式引用用户。它只是不像上一个那样具有双重相关性。无论如何,现在我们已经从用户模式中删除了 pokes 数组。好的!我们不会再冒数据不一致的风险了,注意!我们也不会为每次 poke 做两次更新,toit!现在的权衡是,当我们想要获取用户戳过的用户列表时,我们必须执行与上面我们想要获取用户被戳过的用户列表类似的查询。这还不错,但肯定不如让 pokes 阵列已经坐在那里等待那么快。

在我看来,除非你在搜索谁被戳(而不是被戳)的用户比其他任何事情都要频繁得多,否则这第三种情况是最好的。这些模式具有逻辑意义,您不会更新两次。这是我会使用的。但正如我所说,考虑您的特殊需求和设计非常重要。

希望有帮助!


推荐阅读