Mongodb 查找符合条件的所有子文档
我只想从我的两个对象数组Mongodb 查找符合条件的所有子文档,mongodb,mongoose,mongodb-query,aggregation-framework,Mongodb,Mongoose,Mongodb Query,Aggregation Framework,我只想从我的两个对象数组file\u history和upload\u files中获取满足标准的子文档。尽管我找到了这个答案#2(),但它对我来说并没有达到预期效果,或者我遗漏了一些东西 var projectId = req.params.projectId var uploadId = req.body.uploadId let populateQuery = [ {path: 'owner'}, {path: 'uploaded_files.file', match:
file\u history
和upload\u files
中获取满足标准的子文档。尽管我找到了这个答案#2(),但它对我来说并没有达到预期效果,或者我遗漏了一些东西
var projectId = req.params.projectId
var uploadId = req.body.uploadId
let populateQuery = [
{path: 'owner'},
{path: 'uploaded_files.file', match: {upload_id: uploadId}},
{path: 'file_history.file', match: {upload_id: uploadId}}
]
Project.findOne({ project_id: projectId }).populate(populateQuery).then(project => {
console.log(project)
})
我的文档如下所示:
{
"_id" : ObjectId("5935a41f12f3fac949a5f925"),
"project_id" : 13,
"updated_at" : ISODate("2017-07-05T21:45:46.754Z"),
"created_at" : ISODate("2017-06-05T18:34:07.150Z"),
"owner" : ObjectId("591eea4439e1ce33b47e73c3"),
"name" : "RDemo project",
"uploaded_files" : [
{
"display_name" : "Log_28-6-2017_14-17-53-562.txt",
"file" : ObjectId("595c4c4f3ae2470700ea07e2"),
"upload_id" : ObjectId("595c0f7ea1d20247285be5f5"),
"created_at" : ISODate("2017-07-05T02:17:51.000Z")
},
{
"display_name" : "Coon.png",
"file" : ObjectId("595c4c553ae2470700ea07e4"),
"upload_id" : ObjectId("595c4c553ae2470700ea07e5"),
"created_at" : ISODate("2017-07-05T02:17:57.000Z")
}
],
"file_history" : [
{
"display_name" : "account working.txt",
"file" : ObjectId("595c0f7ea1d20247285be5f4"),
"upload_id" : ObjectId("595c0f7ea1d20247285be5f5"),
"created_at" : ISODate("2017-07-04T21:58:22.000Z")
},
{
"display_name" : "Log_28-6-2017_14-17-53-562.txt",
"file" : ObjectId("595c4c4f3ae2470700ea07e2"),
"upload_id" : ObjectId("595c0f7ea1d20247285be5f5"),
"created_at" : ISODate("2017-07-05T02:17:51.000Z")
}
]
}
它将在文件\u历史
和上传的\u文件
中打印项目及其所有子文档。但是,我只想获取与给定上载id匹配的子文档。我做错了什么
编辑:这个问题是指使用猫鼬解决它。我无法在Mongoose中使用这个问题()中的聚合语句,因为它返回了一个空数组,但是我可以通过MongoDB运行它,它确实返回了所需的结果。这就是我尝试过的代码:
let projectId = req.params.projectId // Project ID is an integer and no objectId
let uploadId = new mongoose.Types.ObjectId(req.body.uploadId)
console.log(`ProjectID: ${projectId}, uploadId: ${uploadId}, params: ${req.body.uploadId}`)
let populateQuery = [
{path: 'owner'},
{path: 'uploaded_files.file'},
{path: 'file_history.file'}
]
Project.aggregate(
{$match: {"project_id": projectId}},
{$project: {
uploaded_files: {$filter: {
input: '$uploaded_files',
as: 'uploadedFile',
cond: {$eq: ['$$uploadedFile.upload_id', uploadId]}
}}
}
}
).then(project => {
console.log(project)
})
console.log返回:
ProjectID:13,uploadId:595c0f7ea1d20247285be5f5,params:595c0f7ea1d20247285be5f5
哪个是正确的(ID是存在的)您正在做一些可怕的错误,不清楚这是什么。因此,向你展示的最好方式就是以身作则
还要注意的是,即使是“单一匹配”也不需要这样做,而a只需在此处执行即可:
const async = require('async'),
mongoose = require('mongoose'),
Schema = mongoose.Schema,
ObjectId = require('mongodb').ObjectID
mongoose.set('debug',true)
mongoose.Promise = global.Promise;
mongoose.connect('mongodb://localhost/test');
const doc =
{
"_id" : ObjectId("5935a41f12f3fac949a5f925"),
"project_id" : 13,
"updated_at" : new Date("2017-07-05T21:45:46.754Z"),
"created_at" : new Date("2017-06-05T18:34:07.150Z"),
"owner" : ObjectId("591eea4439e1ce33b47e73c3"),
"name" : "RDemo project",
"uploaded_files" : [
{
"display_name" : "Log_28-6-2017_14-17-53-562.txt",
"file" : ObjectId("595c4c4f3ae2470700ea07e2"),
"upload_id" : ObjectId("595c0f7ea1d20247285be5f5"),
"created_at" : new Date("2017-07-05T02:17:51.000Z")
},
{
"display_name" : "Coon.png",
"file" : ObjectId("595c4c553ae2470700ea07e4"),
"upload_id" : ObjectId("595c4c553ae2470700ea07e5"),
"created_at" : new Date("2017-07-05T02:17:57.000Z")
}
],
"file_history" : [
{
"display_name" : "account working.txt",
"file" : ObjectId("595c0f7ea1d20247285be5f4"),
"upload_id" : ObjectId("595c0f7ea1d20247285be5f5"),
"created_at" : new Date("2017-07-04T21:58:22.000Z")
},
{
"display_name" : "Log_28-6-2017_14-17-53-562.txt",
"file" : ObjectId("595c4c4f3ae2470700ea07e2"),
"upload_id" : ObjectId("595c0f7ea1d20247285be5f5"),
"created_at" : new Date("2017-07-05T02:17:51.000Z")
},
{
"display_name" : "Coon.png",
"file" : ObjectId("595c4c553ae2470700ea07e4"),
"upload_id" : ObjectId("595c4c553ae2470700ea07e5"),
"created_at" : new Date("2017-07-05T02:17:57.000Z")
},
{
"display_name" : "Coon.png",
"file" : ObjectId("595c4c553ae2470700ea07e4"),
"upload_id" : ObjectId("595c4c553ae2470700ea07e5"),
"created_at" : new Date("2017-07-05T02:17:57.000Z")
}
]
};
const Test = mongoose.model('Test', new Schema({}, { strict: false }) );
function log(data) {
console.log(JSON.stringify(data, undefined, 2))
}
async.series(
[
// Clean data
(callback) =>
async.each(mongoose.models,(model,callback) =>
model.remove({},callback),callback),
// Insert data
(callback) => Test.insertMany(doc,callback),
// Correct usage of $filter
(callback) =>
Test.aggregate(
[
{ "$match": { "project_id": 13 } },
{ "$addFields": {
"uploaded_files": {
"$filter": {
"input": "$uploaded_files",
"as": "f",
"cond": {
"$eq": [
"$$f.upload_id", ObjectId("595c0f7ea1d20247285be5f5")
]
}
}
},
"file_history": {
"$filter": {
"input": "$file_history",
"as": "f",
"cond": {
"$eq": [
"$$f.upload_id", ObjectId("595c0f7ea1d20247285be5f5")
]
}
}
}
}}
],
(err,results) => {
if (err) callback(err);
log(results);
callback();
}
),
// Just a normal positional project for 1 match
(callback) => Test.findOne(
{ "uploaded_files.upload_id": ObjectId("595c0f7ea1d20247285be5f5") },
{ "uploaded_files.$": 1 },
(err,result) => {
if (err) callback(err);
log(result);
callback();
}
)
],
(err) => {
if (err) throw err;
mongoose.disconnect();
}
)
产生所需的输出:
[
{
"_id": "5935a41f12f3fac949a5f925",
"__v": 0,
"project_id": 13,
"updated_at": "2017-07-05T21:45:46.754Z",
"created_at": "2017-06-05T18:34:07.150Z",
"owner": "591eea4439e1ce33b47e73c3",
"name": "RDemo project",
"uploaded_files": [
{
"created_at": "2017-07-05T02:17:51.000Z",
"upload_id": "595c0f7ea1d20247285be5f5",
"file": "595c4c4f3ae2470700ea07e2",
"display_name": "Log_28-6-2017_14-17-53-562.txt"
}
],
"file_history": [
{
"created_at": "2017-07-04T21:58:22.000Z",
"upload_id": "595c0f7ea1d20247285be5f5",
"file": "595c0f7ea1d20247285be5f4",
"display_name": "account working.txt"
},
{
"created_at": "2017-07-05T02:17:51.000Z",
"upload_id": "595c0f7ea1d20247285be5f5",
"file": "595c4c4f3ae2470700ea07e2",
"display_name": "Log_28-6-2017_14-17-53-562.txt"
}
]
}
]
Mongoose: tests.findOne({ 'uploaded_files.upload_id': ObjectId("595c0f7ea1d20247285be5f5") }, { fields: { 'uploaded_files.$': 1 } })
{
"_id": "5935a41f12f3fac949a5f925",
"uploaded_files": [
{
"display_name": "Log_28-6-2017_14-17-53-562.txt",
"file": "595c4c4f3ae2470700ea07e2",
"upload_id": "595c0f7ea1d20247285be5f5",
"created_at": "2017-07-05T02:17:51.000Z"
}
]
}
根据您之前的问题,您的模式是“嵌入的”,而
.populate()
用于实际数据位于其他集合中的“引用”模式。显示您的实际文档以及您希望实现的目标。哦,好的,我忘记添加文档了!我认为这里的要点是,它很可能是“嵌入的”,这是您需要了解的区别MongoDB和Mongoose之间没有区别。查询语法相同。Mongoose只是一个驱动程序实现,而不是它自己的东西。因为没有将“字符串”强制转换到ObjectId
中,所以得到了一个“空数组”。这很好,它要么起作用,要么不起作用。如果没有得到结果,那么按照实际建议,实际使用核心驱动程序的导入。如果仍然没有得到结果,那么您的输入是错误的,您应该通过硬编码这些值来检查,然后调试为什么会得到不同的输入。$filter
语句是正确的,所以这都是关于您提供的实际值。我认为projectId被视为“字符串”,而不是整数。在将其解析为整数后,它按预期工作。这很奇怪,因为对于find/findOne来说,它在没有解析的情况下工作。谢谢你的帮助