我有一个文档,其中包含这样的数据:
{
"data":"string"
"arrayofdata" :[
{},
{},
{}
]
}我想要做的是只选择单个文档中的数据数组
我正在尝试获得这样的格式:
{ arrayofdata: [{},
{},
{}]}我尝试的结果并不是很好:
[ { arrayofdata: {} },
{ arrayofdata: {} },
{ arrayofdata: {} } ]你知道怎么解决这个问题吗?
这是我目前正在使用的:
async findSubElement(collection: string, subElementName: string, filter: {
id?: number,
offset?: number,
limit?: number,
order?: number,
sort?: string,
fields?: string[],
}): Promise<any[]> {
try {
const aggregatePipeline: any = [];
aggregatePipeline.push(
{
$unwind: '$' + subElementName,
},
);
if (filter.sort) {
filter.sort = subElementName + '.' + filter.sort;
}
// then we can apply filter on these documents
aggregatePipeline.push(
{
$match: {
_id: new ObjectID(filter.id),
},
},
{
$sort: {
[filter.sort ? filter.sort : subElementName + '.created_at']: filter.order || 1,
},
},
// Then, use the offset
{
$skip: filter.offset || 0,
},
// And the limit
{
$limit: filter.limit || 20,
},
);
const fields: any = {};
// If the user specified fields, build the 'fields' object in a Mongo way
if (filter.fields && filter.fields.length > 0) {
filter.fields.forEach(field => {
fields[field] = '$' + subElementName + '.' + field;
});
} else {
// If the user didn't specify any field, use a default value
fields[subElementName] = 1;
}
fields['_id'] = false;
// finally we "project" only the fields of our wanted subDocuments.
aggregatePipeline.push({
$project: fields,
});
const agg = await this.aggregate(
collection,
aggregatePipeline,
);
const result = await agg.toArray();
return result.filter(a => a);
} catch (error) {
throw error;
}
}发布于 2017-08-01 05:55:10
您需要去掉$unwind阶段,简单地使用$project,如下所示:
aggregatePipeline.push(
{
{
$project:
{
"_id": 0 /* get rid of _id explicitly */,
"arrayofdata": "$arrayofdata" /* only include arrayofdata field */
}
}
}
);关于你的评论:是的,你也可以使用一个标准的findOne()。实际上,您在代码中所做的所有工作都可以也应该在不使用聚合框架的情况下完成。请注意,只有当您的查询可以返回多个文档时,sort()、skip()和limit()才可用,因此对于findOne(),它们都不起作用。但是,它们都是使用findMany()工作的
您的$match会变成一个bog标准的过滤器(findOne的第一个参数),如下所示:
collection.findOne({_id: new ObjectID(filter.id)})您的投影将成为findOne方法的$project参数:
// exclude "_id", include "arrayofdata"
collection.findOne({...}, {"_id": 0, "arrayofdata": 1})$sort阶段变成一个.sort()命令:
// I'm not sure about the square brackets here but if your code works then this should work, too.
collection.findOne(...).sort([filter.sort ? filter.sort : subElementName + '.created_at']: filter.order || 1)不过,要注意排序部分,并确保您理解这一点:How to project in MongoDB after sort?
$skip也是如此
collection.findOne(...).sort(...).skip(filter.offset || 0)也适用于$limit
collection.findOne(...).sort(...).skip(...).limit(filter.limit || 20)综上所述,下面是一个有效的查询,它可能在您的数据上下文中有意义,也可能没有意义,但它在语法上是正确的:
collection.find({_id: ObjectId("597fa64617a1cdcf9ace4712")}, {"_id": 0, "arrayofdata": 1}).sort({"arraydata":1}).skip(10).limit(20)https://stackoverflow.com/questions/45416800
复制相似问题