You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在MongoDB中基于子文档实现按玩家权限的条件投影?

解决MongoDB基于用户ID过滤城市敏感字段的查询需求

原始文档结构

{
  "map": {
    "cities": [
      {
        "name": "City1",
        "x": 15,
        "y": 5,
        "owner": 1,
        "defense": 6,
        "income": 35
      },
      {
        "name": "City2",
        "x": 12,
        "y": 14,
        "owner": 0,
        "defense": 4,
        "income": 16
      },
      {
        "name": "City3",
        "x": 6,
        "y": 19,
        "owner": 2,
        "defense": 3,
        "income": 12
      }
    ]
  },
  "players": [
    {
      "userid": "64d3ebfb42fb5b118b928f5c",
      "faction": 1
    },
    {
      "userid": "636f89f0d4666b666237cec8",
      "faction": 2
    }
  ]
}

查询需求

  • 仅接收userid作为输入,返回过滤后的地图数据
  • 核心规则:
    1. 仅当玩家所属派系(players.faction)与城市所属派系(map.cities.owner)匹配时,显示该城市的defense和income实际值
    2. 非玩家所属城市不显示defense和income(或默认设为0)

示例返回结果

查询userid="64d3ebfb42fb5b118b928f5c"时

{
  "map": {
    "cities": [
      {
        "name": "City1",
        "x": 15,
        "y": 5,
        "owner": 1,
        "defense": 6,
        "income": 35
      },
      {
        "name": "City2",
        "x": 12,
        "y": 14,
        "owner": 0
      },
      {
        "name": "City3",
        "x": 6,
        "y": 19,
        "owner": 2
      }
    ]
  }
}

查询userid="636f89f0d4666b666237cec8"时

{
  "map": {
    "cities": [
      {
        "name": "City1",
        "x": 15,
        "y": 5,
        "owner": 1
      },
      {
        "name": "City2",
        "x": 12,
        "y": 14,
        "owner": 0
      },
      {
        "name": "City3",
        "x": 6,
        "y": 19,
        "owner": 2,
        "defense": 3,
        "income": 12
      }
    ]
  }
}

解决方案:MongoDB聚合查询

使用聚合管道实现字段过滤,以下是完整查询语句(将<输入的userid>替换为实际参数):

db.collection.aggregate([
  // 1. 匹配包含目标用户的文档
  {
    $match: {
      "players.userid": "<输入的userid>"
    }
  },
  // 2. 提取当前用户的派系ID,存入临时字段
  {
    $addFields: {
      currentFaction: {
        $arrayElemAt: [
          { $filter: {
              input: "$players",
              cond: { $eq: ["$$this.userid", "<输入的userid>"] }
            }
          },
          0
        ]
      }
    }
  },
  // 3. 遍历城市数组,按规则过滤敏感字段
  {
    $addFields: {
      "map.cities": {
        $map: {
          input: "$map.cities",
          as: "city",
          in: {
            name: "$$city.name",
            x: "$$city.x",
            y: "$$city.y",
            owner: "$$city.owner",
            // 仅匹配派系时保留defense,否则移除字段(或改为0)
            defense: {
              $cond: {
                if: { $eq: ["$$city.owner", "$currentFaction.faction"] },
                then: "$$city.defense",
                else: "$$REMOVE"
              }
            },
            // 仅匹配派系时保留income,否则移除字段(或改为0)
            income: {
              $cond: {
                if: { $eq: ["$$city.owner", "$currentFaction.faction"] },
                then: "$$city.income",
                else: "$$REMOVE"
              }
            }
          }
        }
      }
    }
  },
  // 4. 只返回最终需要的map字段
  {
    $project: {
      map: 1,
      _id: 0
    }
  }
])

代码说明

  • $match:快速定位到包含目标用户的游戏文档
  • $filter + $arrayElemAt:从players数组中提取当前用户的派系信息,避免后续重复遍历
  • $map + $cond:逐个处理城市数据,通过条件判断控制敏感字段的显示逻辑,若需要默认值0,将$$REMOVE替换为0即可
  • $project:清理返回结果,只保留所需的map字段

内容的提问来源于stack exchange,提问作者scratch

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 13:31:02