创建 Mongoose 从多个表中查找并填充 属性 集
Create Mongoose Find and populate from multiple tables with property set
对于 Mongoose 的帮助,我将不胜感激。我有 3 tables:(Users)Table 用户,(Animals)table 动物和 table AnimalComments。所以 (AnimalComments)table 引用用户和动物。
const schemaComment = new mongoose.Schema({
userRef: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
animalRef: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Animal'
},
content: {
type: String
}
});
const schemaAnimal = new mongoose.Schema({
name: {
type: String
},
isCommentedByMe: {
type : Boolean,
default: false
},
commentCount: {
type : Number,
default: 0
}
});
我想要什么:我有动物。用户可以给动物添加评论。当用户评论动物时,他的评论被添加到 table AnimalComments,其中存储了 userRef (userId)、animalRef (animalId) 和用户评论文本。然后在请求响应中,我想要 return 来自 table Animals 的所有动物,但我需要根据 table AnimalComments 的值更新 属性 commentCount 和 isCommentedByMe。
table 动物的回应:
{
"animals": [
{
"isCommentedByMe": false,
"commentCount": 0,
"name": "Jessica",
"userRef": {
"id": "5dc9bdf3dd5cae00177e184d"
},
"id": "5dcedd48368e9800176f2ef3"
}
]
}
table 用户的回复:
{
"users": [
{
"name": "Jony Cash",
"id": "5dc9bdf3dd5cae00177e184d"
}
]
}
来自 table 动物评论的回复:
{
"comments": [
{
"userRef": "5dc9bdf3dd5cae00177e184d",
"animalRef": "5dcedd48368e9800176f2ef3",
"content": "Sample text"
}
]
}
我想要例如结果:
{
"animals": [
{
"isCommentedByMe": true,
"commentCount": 4,
"name": "Jessica",
"userRef": {
"id": "5dc9bdf3dd5cae00177e184d"
},
"id": "5dcedd48368e9800176f2ef3"
}
]
}
您不需要在动物模式中保留 isCommentedByMe 和 commentCount 字段。
并且您需要能够访问您的动物的评论。但在动物模式中,没有建立这种联系的领域。所以我们需要使用虚拟人口。
所以你的动物模式必须是这样的:
const schemaAnimal = new mongoose.Schema(
{
name: {
type: String
}
},
{
toJSON: { virtuals: true },
toObject: { virtuals: true }
}
);
// Virtual populate
schemaAnimal.virtual("comments", {
ref: "Comment", //must be changed to the name you used for Comment model.
foreignField: "animalRef",
localField: "_id"
});
现在,我们可以使用以下代码来填充评论。
router.get("/animals", async (req, res) => {
const animals = await Animal.find({}).populate("comments");
res.send(animals);
});
这会给你这样的结果:
[
{
"_id": "5dd66c73069f88614c12b394",
"name": "Animal 1",
"__v": 0,
"comments": [
{
"_id": "5dd66cfd069f88614c12b39a",
"userRef": "5dd66b54c5195127ec5a1b82",
"animalRef": "5dd66c73069f88614c12b394",
"content": "User 1 - Animal 1",
"__v": 0
},
{
"_id": "5dd66d30069f88614c12b39d",
"userRef": "5dd66b71c5195127ec5a1b83",
"animalRef": "5dd66c73069f88614c12b394",
"content": "User 2 - Animal 1",
"__v": 0
}
],
"id": "5dd66c73069f88614c12b394"
},
{
"_id": "5dd66c7d069f88614c12b395",
"name": "Animal 2",
"__v": 0,
"comments": [
{
"_id": "5dd66d09069f88614c12b39b",
"userRef": "5dd66b54c5195127ec5a1b82",
"animalRef": "5dd66c7d069f88614c12b395",
"content": "User 1 - Animal 2",
"__v": 0
}
],
"id": "5dd66c7d069f88614c12b395"
},
{
"_id": "5dd66c88069f88614c12b396",
"name": "Animal 3",
"__v": 0,
"comments": [
{
"_id": "5dd66d46069f88614c12b39e",
"userRef": "5dd66b71c5195127ec5a1b83",
"animalRef": "5dd66c88069f88614c12b396",
"content": "User 2 - Animal 3",
"__v": 0
}
],
"id": "5dd66c88069f88614c12b396"
}
]
要将此结果转换为您想要的结果,我们可以像这样使用地图:
请注意,您需要将 loggedInUserId 变量设置为登录用户的 ID。
router.get("/animals", async (req, res) => {
const loggedInUserId = "5dd66b54c5195127ec5a1b82";
const animals = await Animal.find({}).populate("comments");
const result = animals.map(animal => {
return {
id: animal._id,
name: animal.name,
isCommentedByMe:
animal.comments.filter(c => c.userRef.toString() === loggedInUserId)
.length > 0,
commentCount: animal.comments.length
};
});
res.send(result);
});
结果会是这样的:
[
{
"id": "5dd66c73069f88614c12b394",
"name": "Animal 1",
"isCommentedByMe": true,
"commentCount": 2
},
{
"id": "5dd66c7d069f88614c12b395",
"name": "Animal 2",
"isCommentedByMe": true,
"commentCount": 1
},
{
"id": "5dd66c88069f88614c12b396",
"name": "Animal 3",
"isCommentedByMe": false,
"commentCount": 1
}
]
评论中问题的答案是:(如何引用用户)
const animals = await Animal.find({}).populate({
path: "comments",
model: Comment,
populate: [
{
path: "userRef",
model: User
}
]
});
这会给你这样的 userRef:
[
{
"_id": "5dd66c73069f88614c12b394",
"name": "Animal 1",
"__v": 0,
"comments": [
{
"_id": "5dd66cfd069f88614c12b39a",
"userRef": {
"_id": "5dd66b54c5195127ec5a1b82",
"name": "User 1",
"__v": 0
},
"animalRef": "5dd66c73069f88614c12b394",
"content": "User 1 - Animal 1",
"__v": 0
},
{
"_id": "5dd66d30069f88614c12b39d",
"userRef": {
"_id": "5dd66b71c5195127ec5a1b83",
"name": "User 2",
"__v": 0
},
"animalRef": "5dd66c73069f88614c12b394",
"content": "User 2 - Animal 1",
"__v": 0
}
],
"id": "5dd66c73069f88614c12b394"
},
{
"_id": "5dd66c7d069f88614c12b395",
"name": "Animal 2",
"__v": 0,
"comments": [
{
"_id": "5dd66d09069f88614c12b39b",
"userRef": {
"_id": "5dd66b54c5195127ec5a1b82",
"name": "User 1",
"__v": 0
},
"animalRef": "5dd66c7d069f88614c12b395",
"content": "User 1 - Animal 2",
"__v": 0
}
],
"id": "5dd66c7d069f88614c12b395"
},
{
"_id": "5dd66c88069f88614c12b396",
"name": "Animal 3",
"__v": 0,
"comments": [
{
"_id": "5dd66d46069f88614c12b39e",
"userRef": {
"_id": "5dd66b71c5195127ec5a1b83",
"name": "User 2",
"__v": 0
},
"animalRef": "5dd66c88069f88614c12b396",
"content": "User 2 - Animal 3",
"__v": 0
}
],
"id": "5dd66c88069f88614c12b396"
}
]
对于 Mongoose 的帮助,我将不胜感激。我有 3 tables:(Users)Table 用户,(Animals)table 动物和 table AnimalComments。所以 (AnimalComments)table 引用用户和动物。
const schemaComment = new mongoose.Schema({
userRef: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
animalRef: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Animal'
},
content: {
type: String
}
});
const schemaAnimal = new mongoose.Schema({
name: {
type: String
},
isCommentedByMe: {
type : Boolean,
default: false
},
commentCount: {
type : Number,
default: 0
}
});
我想要什么:我有动物。用户可以给动物添加评论。当用户评论动物时,他的评论被添加到 table AnimalComments,其中存储了 userRef (userId)、animalRef (animalId) 和用户评论文本。然后在请求响应中,我想要 return 来自 table Animals 的所有动物,但我需要根据 table AnimalComments 的值更新 属性 commentCount 和 isCommentedByMe。
table 动物的回应:
{
"animals": [
{
"isCommentedByMe": false,
"commentCount": 0,
"name": "Jessica",
"userRef": {
"id": "5dc9bdf3dd5cae00177e184d"
},
"id": "5dcedd48368e9800176f2ef3"
}
]
}
table 用户的回复:
{
"users": [
{
"name": "Jony Cash",
"id": "5dc9bdf3dd5cae00177e184d"
}
]
}
来自 table 动物评论的回复:
{
"comments": [
{
"userRef": "5dc9bdf3dd5cae00177e184d",
"animalRef": "5dcedd48368e9800176f2ef3",
"content": "Sample text"
}
]
}
我想要例如结果:
{
"animals": [
{
"isCommentedByMe": true,
"commentCount": 4,
"name": "Jessica",
"userRef": {
"id": "5dc9bdf3dd5cae00177e184d"
},
"id": "5dcedd48368e9800176f2ef3"
}
]
}
您不需要在动物模式中保留 isCommentedByMe 和 commentCount 字段。
并且您需要能够访问您的动物的评论。但在动物模式中,没有建立这种联系的领域。所以我们需要使用虚拟人口。
所以你的动物模式必须是这样的:
const schemaAnimal = new mongoose.Schema(
{
name: {
type: String
}
},
{
toJSON: { virtuals: true },
toObject: { virtuals: true }
}
);
// Virtual populate
schemaAnimal.virtual("comments", {
ref: "Comment", //must be changed to the name you used for Comment model.
foreignField: "animalRef",
localField: "_id"
});
现在,我们可以使用以下代码来填充评论。
router.get("/animals", async (req, res) => {
const animals = await Animal.find({}).populate("comments");
res.send(animals);
});
这会给你这样的结果:
[
{
"_id": "5dd66c73069f88614c12b394",
"name": "Animal 1",
"__v": 0,
"comments": [
{
"_id": "5dd66cfd069f88614c12b39a",
"userRef": "5dd66b54c5195127ec5a1b82",
"animalRef": "5dd66c73069f88614c12b394",
"content": "User 1 - Animal 1",
"__v": 0
},
{
"_id": "5dd66d30069f88614c12b39d",
"userRef": "5dd66b71c5195127ec5a1b83",
"animalRef": "5dd66c73069f88614c12b394",
"content": "User 2 - Animal 1",
"__v": 0
}
],
"id": "5dd66c73069f88614c12b394"
},
{
"_id": "5dd66c7d069f88614c12b395",
"name": "Animal 2",
"__v": 0,
"comments": [
{
"_id": "5dd66d09069f88614c12b39b",
"userRef": "5dd66b54c5195127ec5a1b82",
"animalRef": "5dd66c7d069f88614c12b395",
"content": "User 1 - Animal 2",
"__v": 0
}
],
"id": "5dd66c7d069f88614c12b395"
},
{
"_id": "5dd66c88069f88614c12b396",
"name": "Animal 3",
"__v": 0,
"comments": [
{
"_id": "5dd66d46069f88614c12b39e",
"userRef": "5dd66b71c5195127ec5a1b83",
"animalRef": "5dd66c88069f88614c12b396",
"content": "User 2 - Animal 3",
"__v": 0
}
],
"id": "5dd66c88069f88614c12b396"
}
]
要将此结果转换为您想要的结果,我们可以像这样使用地图:
请注意,您需要将 loggedInUserId 变量设置为登录用户的 ID。
router.get("/animals", async (req, res) => {
const loggedInUserId = "5dd66b54c5195127ec5a1b82";
const animals = await Animal.find({}).populate("comments");
const result = animals.map(animal => {
return {
id: animal._id,
name: animal.name,
isCommentedByMe:
animal.comments.filter(c => c.userRef.toString() === loggedInUserId)
.length > 0,
commentCount: animal.comments.length
};
});
res.send(result);
});
结果会是这样的:
[
{
"id": "5dd66c73069f88614c12b394",
"name": "Animal 1",
"isCommentedByMe": true,
"commentCount": 2
},
{
"id": "5dd66c7d069f88614c12b395",
"name": "Animal 2",
"isCommentedByMe": true,
"commentCount": 1
},
{
"id": "5dd66c88069f88614c12b396",
"name": "Animal 3",
"isCommentedByMe": false,
"commentCount": 1
}
]
评论中问题的答案是:(如何引用用户)
const animals = await Animal.find({}).populate({
path: "comments",
model: Comment,
populate: [
{
path: "userRef",
model: User
}
]
});
这会给你这样的 userRef:
[
{
"_id": "5dd66c73069f88614c12b394",
"name": "Animal 1",
"__v": 0,
"comments": [
{
"_id": "5dd66cfd069f88614c12b39a",
"userRef": {
"_id": "5dd66b54c5195127ec5a1b82",
"name": "User 1",
"__v": 0
},
"animalRef": "5dd66c73069f88614c12b394",
"content": "User 1 - Animal 1",
"__v": 0
},
{
"_id": "5dd66d30069f88614c12b39d",
"userRef": {
"_id": "5dd66b71c5195127ec5a1b83",
"name": "User 2",
"__v": 0
},
"animalRef": "5dd66c73069f88614c12b394",
"content": "User 2 - Animal 1",
"__v": 0
}
],
"id": "5dd66c73069f88614c12b394"
},
{
"_id": "5dd66c7d069f88614c12b395",
"name": "Animal 2",
"__v": 0,
"comments": [
{
"_id": "5dd66d09069f88614c12b39b",
"userRef": {
"_id": "5dd66b54c5195127ec5a1b82",
"name": "User 1",
"__v": 0
},
"animalRef": "5dd66c7d069f88614c12b395",
"content": "User 1 - Animal 2",
"__v": 0
}
],
"id": "5dd66c7d069f88614c12b395"
},
{
"_id": "5dd66c88069f88614c12b396",
"name": "Animal 3",
"__v": 0,
"comments": [
{
"_id": "5dd66d46069f88614c12b39e",
"userRef": {
"_id": "5dd66b71c5195127ec5a1b83",
"name": "User 2",
"__v": 0
},
"animalRef": "5dd66c88069f88614c12b396",
"content": "User 2 - Animal 3",
"__v": 0
}
],
"id": "5dd66c88069f88614c12b396"
}
]