当revisions
是一个对象(键是entryid)时,我有一个聚合调用正在工作。
await Project.aggregate([
{ $limit: 1 },
{ $match: { _id: ObjectId(projectId) } },
{
$project: {
limits: 1,
revisions: { $slice: [`$revisions.${entryId}.${languageId}`, startIndex, PageSize] },
totalRevisions: {
$size: { $ifNull: [`$revisions.${entryId}.${languageId}`, []] },
},
},
},
]);
现在,我将
revisions
转换为一个内部有entryid的数组,我不知道如何获得相同的结果。我试过:await Project.aggregate([
{ $limit: 1 },
{
$match: {
_id: ObjectId(projectId),
'revisions.entryId': ObjectId(entryId),
},
},
{
$project: {
limits: 1,
revisions: { $slice: [`$revisions.$.${languageId}`, startIndex, PageSize] },
totalRevisions: {
$size: { $ifNull: [`$revisions.$.${languageId}`, []] },
},
},
},
]);
但我得到了错误:
mongoerror:字段路径字段名不能以“$”开头。
如何对数组中的项使用
$slice
和$ifNull
?谢谢示例文档:
{
"revisions" : [
{
"entryId" : ObjectId("5bbf8813c272e05171463bc4"),
"5bbe76c6d3fb1a4f143f8304" : [
{
"authorId" : ObjectId("5b1c5384d75d9f3b0eb65c2a"),
"revisionId" : ObjectId("5bbf8813c272e05171463bc7"),
"updated" : "2018-10-11T17:27:47.842Z",
"value" : "County"
}
]
}
]
}
最佳答案
管道阶段的顺序在这里非常重要。当您在$limit
之前使用$match
时,它会从$limit
阶段中找到的单个文档中筛选数据。
如果在$match
之前使用$limit
,则它将从数据库中的所有集合中筛选文档,并在$limit
阶段抛出单个文档。
之后,您可以尝试下面的聚合
db.collection.aggregate([
{ "$match": {
"_id": ObjectId(projectId),
"revisions.entryId": ObjectId(entryId)
}},
{
"$project": {
"revisions": {
"$map": {
"input": "$revisions",
"in": {
"$arrayToObject": {
"$map": {
"input": {
"$filter": {
"input": { "$objectToArray": "$$this" },
"as": "ee",
"cond": { "$eq": ["$$ee.k", "5bbe76c6d3fb1a4f143f8304"] }
}
},
"as": "dd",
"in": {
"k": "$$dd.k",
"v": { "$slice": [startIndex, 1 ] }
}
}
}
}
}
},
"totalRevisions": {
"$arrayElemAt": [
{
"$map": {
"input": "$revisions",
"in": {
"$size": {
"$map": {
"input": {
"$filter": {
"input": { "$objectToArray": "$$this" },
"as": "ee",
"cond": { "$eq": ["$$ee.k", "5bbe76c6d3fb1a4f143f8304"] }
}
},
"as": "dd",
"in": {
"k": "$$dd.k",
"v": { "$slice": [startIndex, 1] }
}
}
}
}
}
},
0
]
}
}
}
])
但是如果你刚开始你的项目,我强烈建议你不要使用这种结构,因为你的嵌套数组键是动态的,玩动态键就像玩裸线。