查询包含(或不包含)嵌套文档数组(正在填充)但随后匹配特定条件的文档
Query documents containing (or not) array of nested documents (being populated) but then matching a certain criteria
在标记为“已回答”(或类似的东西)之前请仔细阅读(不仅仅是标题)因为我真的研究了很长时间还没有找到解决方案(我发现了有关查询嵌套数组 objects 的问题,但没有找到需要填充的嵌套数组文档)。
我正在使用最新版本的 NodeJS 和 Mongoose。
为了说明,我将使用这两个模型来帮助描绘我的目标:
// Sections
const mongoose = require('mongoose');
var Schema = mongoose.Schema;
const sectionSchema = new Schema({
_id: Schema.Types.ObjectId,
name: { type: String, required: [true, 'Name is required.']},
});
module.exports = mongoose.model('Section', sectionSchema);
并且:
// Departments
const mongoose = require('mongoose');
var Schema = mongoose.Schema;
const departmentSchema = new Schema({
_id: Schema.Types.ObjectId,
name: { type: String, required: [true, 'Name is required.']},
sections: [{ type: Schema.Types.ObjectId, ref: 'Section' }]
});
module.exports = mongoose.model('Department', departmentSchema);
考虑一下我将这些存储在数据库中:
// Departments
_id: ObjectId("61b0f1971ad3890000000001")
name: "Department 1",
sections: [ObjectId("61b26a3fb756a1000000000b"), ObjectId("61b26a3fb756a1000000000c")]
_id: ObjectId("61b0f1971ad3890000000002")
name: "Department 2",
sections: [ObjectId("61b26a3fb756a1000000000a"), ObjectId("61b26a3fb756a1000000000c")]
_id: ObjectId("61b0f1971ad3890000000003")
name: "Department 3",
sections: []
_id: ObjectId("61b0f1971ad3890000000004")
name: "Department 4",
sections: [ObjectId("61b26a3fb756a1000000000b")]
// Sections
_id: ObjectId("61b26a3fb756a1000000000a")
name: "Section A"
_id: ObjectId("61b26a3fb756a1000000000b")
name: "Section B"
_id: ObjectId("61b26a3fb756a1000000000c")
name: "Section C"
现在,我要做的是获取不包含部分或名称为“A 部分”的部分的部门(来自前端的文本作为过滤器)。
Department.find(criteria).select('name').populate('sections').then(results => {
console.log('Departments: ', results.map(r => r.name));
});
// Should print:
Departments: [ Department 2, Department 3 ]
对于标准,我尝试了很多不同的方法,但 none 到目前为止似乎都有效(我总是得到零结果)。下面一个例子:
const criteria = {
$or: [
{ 'sections': [] },
{ 'sections': { '$elemMatch': { name: 'Section A' }}},
]
};
我认为这是因为 criteria
在查询填充数组之前进行了测试。如果这是正在发生的事情,那么最好的解决方法是什么?我想避免分别查询两个文档然后匹配结果。 应该有办法一次性做到这一点。有任何想法吗?提前致谢。
让我们看看您的查询。
您要查找节 [] 或节名称为 'Section A' 的文档。但是在您的 Department 模型中,您只是保存了每个部分的 id。您无法访问 populating.so 之前提交的名称,您需要根据部分 ID 查找文档。
您可以像下面这样更改条件。
const criteria = {
$or: [
{ 'sections': [] },
{ 'sections': mongoose.Types.ObjectId("61b26a3fb756a1000000000a") }
]
};
很明显,您无法访问填充前填写的名称。您也可以对填充进行过滤,但我没有找到涵盖这两种情况的解决方案。您还可以阅读 populate documentations.
一种方法是获取所有文档并填充它们,然后实施过滤器,但我认为这不是一个好方法。
//Fetch and populate all documents
const departments = await Department.find({
}).populate({
path: 'sections',
select: 'name',
}).exec();
let res = [];
departments.forEach(department => {
//Select departments which has "Section A" or has not any section
if (department.sections.some(section => section.name === "Section A") || department.sections.length === 0) {
res.push(department);
}
});
经过详尽的测试和研究,我得出结论,仅通过操纵填充 criteria
的内容无法一次性获得预期结果 。 =14=]
为 querying documents with nested/embedded array of other documents 提供的最接近的 MongoDB 文档不涉及 populate
。
因此,current/next 实现目标的最佳方法(打印不包含部分的部门或 'Section A' 而没有提供 section._id 但仅 section.name ) 是:
Section.find({ name: 'Section A' }).then(sections => {
Department.find({
$or: [
{ 'sections': [] },
{ 'sections': { $in: sections }},
]
}).then(departments => console.log('Departments: ', results.map(r => r.name));
// Will print: Departments: [ Department 2, Department 3 ]
});
在标记为“已回答”(或类似的东西)之前请仔细阅读(不仅仅是标题)因为我真的研究了很长时间还没有找到解决方案(我发现了有关查询嵌套数组 objects 的问题,但没有找到需要填充的嵌套数组文档)。
我正在使用最新版本的 NodeJS 和 Mongoose。
为了说明,我将使用这两个模型来帮助描绘我的目标:
// Sections
const mongoose = require('mongoose');
var Schema = mongoose.Schema;
const sectionSchema = new Schema({
_id: Schema.Types.ObjectId,
name: { type: String, required: [true, 'Name is required.']},
});
module.exports = mongoose.model('Section', sectionSchema);
并且:
// Departments
const mongoose = require('mongoose');
var Schema = mongoose.Schema;
const departmentSchema = new Schema({
_id: Schema.Types.ObjectId,
name: { type: String, required: [true, 'Name is required.']},
sections: [{ type: Schema.Types.ObjectId, ref: 'Section' }]
});
module.exports = mongoose.model('Department', departmentSchema);
考虑一下我将这些存储在数据库中:
// Departments
_id: ObjectId("61b0f1971ad3890000000001")
name: "Department 1",
sections: [ObjectId("61b26a3fb756a1000000000b"), ObjectId("61b26a3fb756a1000000000c")]
_id: ObjectId("61b0f1971ad3890000000002")
name: "Department 2",
sections: [ObjectId("61b26a3fb756a1000000000a"), ObjectId("61b26a3fb756a1000000000c")]
_id: ObjectId("61b0f1971ad3890000000003")
name: "Department 3",
sections: []
_id: ObjectId("61b0f1971ad3890000000004")
name: "Department 4",
sections: [ObjectId("61b26a3fb756a1000000000b")]
// Sections
_id: ObjectId("61b26a3fb756a1000000000a")
name: "Section A"
_id: ObjectId("61b26a3fb756a1000000000b")
name: "Section B"
_id: ObjectId("61b26a3fb756a1000000000c")
name: "Section C"
现在,我要做的是获取不包含部分或名称为“A 部分”的部分的部门(来自前端的文本作为过滤器)。
Department.find(criteria).select('name').populate('sections').then(results => {
console.log('Departments: ', results.map(r => r.name));
});
// Should print:
Departments: [ Department 2, Department 3 ]
对于标准,我尝试了很多不同的方法,但 none 到目前为止似乎都有效(我总是得到零结果)。下面一个例子:
const criteria = {
$or: [
{ 'sections': [] },
{ 'sections': { '$elemMatch': { name: 'Section A' }}},
]
};
我认为这是因为 criteria
在查询填充数组之前进行了测试。如果这是正在发生的事情,那么最好的解决方法是什么?我想避免分别查询两个文档然后匹配结果。 应该有办法一次性做到这一点。有任何想法吗?提前致谢。
让我们看看您的查询。 您要查找节 [] 或节名称为 'Section A' 的文档。但是在您的 Department 模型中,您只是保存了每个部分的 id。您无法访问 populating.so 之前提交的名称,您需要根据部分 ID 查找文档。 您可以像下面这样更改条件。
const criteria = {
$or: [
{ 'sections': [] },
{ 'sections': mongoose.Types.ObjectId("61b26a3fb756a1000000000a") }
]
};
很明显,您无法访问填充前填写的名称。您也可以对填充进行过滤,但我没有找到涵盖这两种情况的解决方案。您还可以阅读 populate documentations.
一种方法是获取所有文档并填充它们,然后实施过滤器,但我认为这不是一个好方法。
//Fetch and populate all documents
const departments = await Department.find({
}).populate({
path: 'sections',
select: 'name',
}).exec();
let res = [];
departments.forEach(department => {
//Select departments which has "Section A" or has not any section
if (department.sections.some(section => section.name === "Section A") || department.sections.length === 0) {
res.push(department);
}
});
经过详尽的测试和研究,我得出结论,仅通过操纵填充 criteria
的内容无法一次性获得预期结果 。 =14=]
为 querying documents with nested/embedded array of other documents 提供的最接近的 MongoDB 文档不涉及 populate
。
因此,current/next 实现目标的最佳方法(打印不包含部分的部门或 'Section A' 而没有提供 section._id 但仅 section.name ) 是:
Section.find({ name: 'Section A' }).then(sections => {
Department.find({
$or: [
{ 'sections': [] },
{ 'sections': { $in: sections }},
]
}).then(departments => console.log('Departments: ', results.map(r => r.name));
// Will print: Departments: [ Department 2, Department 3 ]
});