以下是文档的相关部分的外观:

{
  "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
    }
  ]
}

如果我是Player1(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
      }
    ]
  }
}

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
      }
    ]
  }
}
  • 查询应仅接受用户ID作为输入
  • 只有当"players.side"与"map.cities.owner"匹配时,才会显示"Defense"和"Income"的实际值.
  • 玩家不能看到他/她不拥有的城市的价值
  • 如果玩家不拥有城市,则值默认为例如0

我知道我可以只查询并以编程方式删除它,但我想知道是否可以做得更好.

我试过这样做,但显然不起作用,因为"$map.cities.owner"/"$map.cities.Defense"实际上是一个数组/返回一个array.

{
  _id: 0,
  "map.cities.name": 1,
  "map.cities.x": 1,
  "map.cities.y": 1,
  "map.cities.owner": 1,
  "map.cities.defense": {
    $cond: {
      if: {
        $eq: ["$map.cities.owner", 1],
      },
      then: "$map.cities.defense",
      else: "$$REMOVE",
    },
  },
}

我试着使用$filter,但很快就变得非常麻烦,我从未得到我想要的结果.

我试着在map.cities上使用$unwind,但很难再次将其放入单个文档中.

推荐答案

一种 Select 是使用用户的faction作为var(根据其faction),然后使用$mapmap来过滤它:

db.collection.aggregate([
  {
    $project: {
      "map.cities": {
        $let: {
          vars: {
            faction: {
              "$getField": {
                "input": {
                  $first: {
                    $filter: {
                      input: "$players",
                      cond: {
                        $eq: [
                          "$$this.userid",
                          "64d3ebfb42fb5b118b928f5c"
                        ]
                      }
                    }
                  }
                },
                "field": "faction"
              }
            }
          },
          in: {
            $map: {
              input: "$map.cities",
              in: {
                $mergeObjects: [
                  {
                    name: "$$this.name",
                    "x": "$$this.x",
                    "y": "$$this.y",
                    "owner": "$$this.owner"
                  },
                  {
                    $cond: [
                      {
                        $eq: [
                          "$$this.owner",
                          "$$faction"
                        ]
                      },
                      "$$this",
                      {}
                    ]
                  }
                ]
              }
            }
          }
        }
      }
    }
  }
])

看看它在mongodb playground号公路上是如何工作的

Mongodb相关问答推荐

查找/查找单个深度嵌套文档的多个集合

为什么数组长度0被认为是Mongoose中排序中最大的数字

MongoDB 对特定搜索查询的响应时间较长

数组过滤器 MongoDB

Mongoose 聚合和多级组

从具有多个数组匹配 MongoDB 的两个集合中采样数据

如何将记录从一个 mongo 数据库插入另一个?

Spring Boot MongoDB 连接问题

更新 mongoengine 中的嵌入文档列表

使用 mgo 存储嵌套 struct

Flask and Mongo

在 Nodejs 中找不到模块

如何在任意深度查找 MongoDB 字段名称

try 解析序列化 JSON 字符串时处理 MongoDB 的 ISODate()

在 MongoDB 中按条件分组

如何使用node.js http服务器从mongodb返回大量行?

Flask:设置应用程序和请求特定的属性?

一起使用 MongoDB 和 Neo4j

在mongoose中查询虚拟属性

mongoose查询返回 null