重要提示
下面的所有代码都未经过测试(但是,当我可以设置一个最小的环境时,我会这样做)并且应该适应您的项目。请记住,我不是 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 的列表,您可以返回 Shops 和 Members 的聚合生成包含Shops 和Models 信息的混合文档。这样一来,前端就可以通过一个后端请求获得所需的所有信息。
重要提示
以下代码可能无法按原样运行,您必须对其进行调整,我目前没有什么可以测试它的。请记住,我对聚合不是很熟悉,更不用说 Mongoose,但您可以通过查看代码和 cmets 了解大致的概念。
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 aggregation pipelines
Mongoose aggregates
MongoDB $push operator
MongoDB $pull operator