如何在nodejs+mongodb中对集合进行建模



你好,我是nodejs和mongodb的新手。

我有三种型号:

  1. "用户";其中字段";姓名电话">
  2. "商店"其中字段";姓名、地址">
  3. "成员";其中字段";商店用户状态";。(商店和用户持有各自收藏的"id"(

现在当我创建";商店";api获取所有商店,然后我需要添加额外的字段"isShopJoined";其不是模型的一部分。如果看到该商店的用户加入,则此额外字段将为true,否则将为false。

当我与Android/iOS等前端开发人员共享我的模型时,问题就会发生。在他们看到API响应之前,他们不会意识到这个额外的字段。

那么,如果我在商店列表中添加额外的字段,这不是模型的一部分,可以吗?或者我需要在模型中添加那个额外的字段吗?

重要提示

下面的所有代码都经过了NOT测试(不过,当我可以设置一个最小的环境时,我会这样做(,应该适合您的项目。请记住,我不是MongoDB聚合的专家,更不用说Mongoose了,这里的代码只是为了掌握总体思想和算法。

如果我理解正确,您不必做任何事情,因为信息存储在Member集合中。但它迫使前端执行一个额外的请求(或许多额外的请求(,以同时具有Shops的列表,并(逐个(检查当前登录的用户是否是商店的Member

请记住,前端通常是由数据驱动的(API/后端也是如此(,而不是相反。前端必须适应你给它的东西

如果你对自己所拥有的感到满意,你可以保持这种状态,它会起作用,但这可能不是很有效。

假设:

import mongoose from "mongoose";
const MemberSchema = new mongoose.Schema({
shopId: {
type: ObjectId,
ref: 'ShopSchema',
required: true
},
userId: {
type: ObjectId,
ref: 'UserSchema',
required: true
},
status: {
type: String,
required: true
}
});
const ShopSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
address: {
//your address model
}
});
const UserSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
phone: {
type: String,
required: true,
},
// Add something like this
shopsJoined: {
type: Array,
default: [],
required: true
}
});

你可以通过两种方式来解决这个问题:

MongoDB聚合

当检索(后端(商店列表时,如果您知道提出请求的用户,而不是简单地返回Shops的列表,您可以返回ShopsMembers的聚合,从而生成一个包含ShopsModels信息的混合文档。这样,前端就可以通过一个后端请求获得所需的所有信息。

重要提示

下面的代码可能无法正常工作,您必须对其进行调整,我目前没有任何可供测试的内容。请记住,我对聚合不是很熟悉,更不用说Mongoose了,但您可以通过查看代码和注释来了解大致想法。

const aggregateShops = async (req, res, next) => {
try {
// $lookup will merge the "Model" and "Shop" documents into one
// $match will return only the results matching the condition
const aggreg = await Model.aggregate({$lookup: {
from: 'members', //the name of the mongodb collection
localField: '_id', //the "Shop" field to match with foreign collection
foreignField: 'shopId', //the "Member" field to match with local collection
as: 'memberInfo' //the field name in which to store the "Member" fields; 
}, {
$match: {memberInfo: {userId: myUserId}}
}});
// the result should be an array of object looking like this:
/*{
_id: SHOP_OBJECT_ID,
name: SHOP_NAME,
address: SHOP_ADDRESS,
memberInfo: {
shopId: SHOP_OBJECT_ID,
userId: USER_OBJECT_ID,
status: STATUS_JOINED_OR_NOT
}
}*/
// send back the aggregated result to front-end
} catch (e) {
return next(e);
}
}

删除Members集合并将信息存储在其他位置

本能地,我会走这条路。其思想是在User模型中存储阵列字段shopsJoined,或者在Shops模型中存储membersJoined阵列字段。这样,不管怎样,信息都会被检索到,因为您仍然需要检索Shops,并且您已经有了User

// Your PATCH route should look like this
const patchUser = async (req, res, next) => {
try {
// How you chose to proceed here is up to you
// I tend to facilitate front-end work, so get them to send you (via req.body) the shopId to join OR "un-join"
// They should already know what shops are joined or not as they have the User
// For example, req.body.shopId = "+ID" if it's a join, or req.body.shopId = "-ID" if it's an un-join
if (req.body.shopId.startsWith("+")) {
await User.findOneAndUpdate(
{ _id: my_user_id },
{ $push: { shopsJoined: req.body.shopId } }
);
} else if (req.body.shopId.startsWith("-")) {
await User.findOneAndUpdate(
{ _id: my_user_id },
{ $pull: { shopsJoined: req.body.shopId } }
);
} else {
// not formatted correctly, return error
}
// return OK here depending on the framework you use
} catch (e) {
return next(e);
}
};

当然,上面的代码适用于User模型,但您也可以对Shop模型执行同样的操作。

有用的链接:

MongoDB聚合管道

Mongoose聚集体

MongoDB$推送运营商

MongoDB$pull操作符

是的,您必须将字段添加到模型中,因为将其添加到响应中只是键的临时显示,但如果您将来或在某些列表过滤器中需要,该怎么办,所以将其添加至模型中是很好的。

如果你认为前端必须得到通知,那么就去吧,你也可以将一些默认值设置为";isShopJoined";关键是让它暂时停下来。

最新更新