求教关于Nodejs mongo数据同步的问题,求大神

求教关于Nodejs mongo数据同步的问题,求大神

现在有两张表,A和B,A是记录用户信息的表,B是记录用户发布的文章内容的表。

我现在在B中有个字段是用来记录A中的用户名的,这样可以让我我知道B中的文章都是哪些用户发布的,但是现在遇到的问题是如果A表中的用户字段被用户自己修改了,但是B表中用户名这个字段如何才能跟着A表的修改一起同步了。

现在有一种解决方法是我在B表记录A的表用户的ID,然后每次读取B表的数据的时候去查询A表的用户信息,但是这样性能太低了,因为假设我现在在做一个文章列表需要展示用户名这个字段,那我没展示一条文章就需要去查询一次A表。


9 回复

对于这个问题,我们可以使用MongoDB的引用或者嵌入的方式来解决。下面是两种可能的解决方案:

解决方案一:使用MongoDB的引用

在这种情况下,我们在B表中存储A表的用户ID而不是用户名。这样,当A表中的用户名发生变化时,我们只需要更新一个地方即可。

示例代码:

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

// 用户模型
const UserSchema = new Schema({
    username: { type: String, required: true },
    // 其他用户字段...
});

const User = mongoose.model('User', UserSchema);

// 文章模型
const ArticleSchema = new Schema({
    userId: { type: Schema.Types.ObjectId, ref: 'User' }, // 引用用户ID
    title: { type: String, required: true },
    content: { type: String, required: true }
});

const Article = mongoose.model('Article', ArticleSchema);

使用场景:

// 更新用户信息
async function updateUser(userId, newUsername) {
    await User.findByIdAndUpdate(userId, { username: newUsername });
}

// 获取文章列表
async function getArticles() {
    const articles = await Article.find().populate('userId'); // 使用populate自动填充用户信息
    return articles.map(article => ({
        ...article.toObject(),
        username: article.userId.username
    }));
}

解决方案二:使用嵌入式文档

如果我们不希望每次都去查询数据库,可以选择将用户信息嵌入到文章文档中。这样,即使用户信息发生变化,我们也需要手动更新所有相关的文章。

示例代码:

const ArticleSchema = new Schema({
    user: {
        id: { type: Schema.Types.ObjectId, ref: 'User' },
        username: { type: String, required: true }
    },
    title: { type: String, required: true },
    content: { type: String, required: true }
});

使用场景:

// 更新用户信息
async function updateUser(userId, newUsername) {
    await User.findByIdAndUpdate(userId, { username: newUsername });
    await Article.updateMany({ 'user.id': userId }, { $set: { 'user.username': newUsername } });
}

这两种方法各有优缺点,具体选择哪种取决于你的应用场景和需求。第一种方法(引用)更灵活,而第二种方法(嵌入)在某些情况下可以提高性能。


我觉得存id再获取id对应的信息这个方法是合理的。相当于Mongoose的populate, 数据量大时可能会查询慢。 但是用户信息完全可以用Memcache或者Redis缓存下来,这样理论上查询会比较快,但是在数据量还不大时没必要这样做。

感觉到性能瓶颈了,再优化这地方,否则还是以维护性优先。 同时更新两个表,你是不是还得实现事务管理,万一失败记得回滚

请使用 sql。

不同用户发的文章列表很简单啊,你只要把文章先查出来,然后把用户id收集起来,一次性查出来。

而且我觉得mongoose的populate可能有类似的优化哟,这样你就可以直接用populate了,只用读两次数据库而已啦,别这么爱护你的服务器。。。

这样你不觉得数据冗余吗?

既然用了mongodb,那么就只能承担no sql带来的特性

对于这个问题,可以使用MongoDB的引用或者嵌入的方式来实现数据同步。

方案一:使用引用

在B表中保存A表中的用户ID,而不是用户名。当需要显示用户名时,再根据用户ID去查询A表中的用户名。

示例代码:

const mongoose = require('mongoose');

const userSchema = new mongoose.Schema({
    username: String,
    // 其他字段
});

const articleSchema = new mongoose.Schema({
    userId: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
    content: String,
    // 其他字段
});

const User = mongoose.model('User', userSchema);
const Article = mongoose.model('Article', articleSchema);

// 添加文章时
async function addArticle(userId, content) {
    const user = await User.findById(userId);
    if (!user) throw new Error('User not found');
    
    const article = new Article({ userId, content });
    await article.save();
}

// 获取文章列表并显示用户名
async function getArticles() {
    const articles = await Article.find().populate('userId', 'username');
    return articles.map(article => ({
        ...article.toObject(),
        username: article.userId.username
    }));
}

方案二:使用嵌入

在B表中直接嵌入A表的用户名,但这种方法不推荐,因为如果A表中的用户名发生变化,B表中的数据不会自动更新。

总结

方案一(使用引用)是更推荐的方式,因为它可以在保证性能的同时保持数据的一致性。通过使用populate方法,可以在查询时动态地加载关联的数据,避免每次都去查询A表。

回到顶部