我正在考虑对猫鼬使用以下问题的最佳实践。
我有三种模式:
const SchemaA = new Schema({
name: String
});
const SchemaB = new Schema({
schemaA: {
type: Schema.Types.ObjectId,
ref: 'SchemaA',
required: true
}
});
const SchemaC = new Schema({
schemaB: {
type: Schema.Types.ObjectId,
ref: 'SchemaB'
},
user: {
type: Schema.Types.ObjectId,
ref: 'User'
}
});
我需要通过附加了schemaC的schemaA id来获取schemaB对象,但必须由用户过滤。
getSchemaBs: async (schemaAId, userId) => {
try {
SchemaB.find({ schemaA: schemaAId }).populate('schemaC': where user === userId);
} catch (e) {
throw new Error('An error occurred while getting schemasB for specified schemaA.');
};
我正在重构使用针对NodeJS的Mongo本机驱动程序编写的代码。现在,我想使用Mongoose使其更简单。
早期版本的代码(请记住,它不能遵循最佳实践):
getList: function (schemaAId, userId) {
return new Promise(
function (resolve, reject) {
db.collection('schemaB').aggregate([{
$match: {
'isDeleted': false,
'schemaA': ObjectID(schemaAId)
}
},
{
$lookup: {
from: "schemaC",
localField: "_id",
foreignField: "schemaBId",
as: "schemasC"
},
},
{
$project: {
_id: true,
schemaAId: true,
// other neccessary fields with true (several lines - makes code ugly and messy)
schemasC: {
"$arrayElemAt": [{
$filter: {
input: "$schamasC",
as: "schemaC",
cond: {
$eq: ["$$schemaC.userId", ObjectID(userId)]
}
}
}, 0]
}
}
}
]).toArray(function (error, result) {
if (error) {
reject(error);
} else {
resolve(result);
};
});
});
}
我该如何处理最好的方法?
答案 0 :(得分:1)
使用mongodb 3.6 $lookup
语法可以更好地完成您想做的事情,该语法可以过滤$lookup
管道内的文档
db.collection('schemaB').aggregate([
{ "$match": { "isDeleted": false, "schemaA": ObjectID(schemaAId) }},
{ "$lookup": {
"from": "schemaC",
"let": { "schemaBId": "$_id" },
"pipeline": [
{ "$match": {
"$expr": { "$eq": ["$schemaBId", "$$schemaBId"] },
"userId": ObjectID("5b5c747d8209982630bbffe5")
}}
],
"as": "schemasC"
}}
])