mongodb - 如何在 MongoDB 中使用数组位置 $ 和聚合投影

标签 mongodb aggregation-framework

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: FieldPath field names may not start with '$'.

如何对数组中的项目使用 $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
        ]
      }
    }
  }
])

但是如果你刚刚开始你的项目,那么我强烈建议你不要使用这种结构,因为你的嵌套数组键是动态的,使用动态键就像玩裸露的电线一样。

关于mongodb - 如何在 MongoDB 中使用数组位置 $ 和聚合投影,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52805492/

相关文章:

Mongodb聚合查找只返回数组的一个字段

javascript - 从 $arrayElemAt 结果中选择字段

mongodb - 查找每天的最后一条记录

python - 从 mongoDB 中提取信息

javascript - $resource service .success 不是一个函数

node.js - mongoose,使用collection.insert后获取对象的id

javascript - MongoDB atlas 连接失败,出现错误 MongoServerSelectionError : connection <monitor> to 52. 64.0.234:27017 closed

从 R 调用时 C++ 程序无法运行(符号查找错误)

regex - 展开对象数组 mongoDB

node.js - Mongodb聚合$match mongo和javascript之间日期处理不一致