查询子文档的嵌套数组

时间:2020-08-08 12:59:34

标签: arrays mongodb typescript subdocument

编辑:查询中不应使用'&'字符。那些字符或用于更新。

ANSWER:由Gibbs提供

correct: 
const result : any = await mongoose.model('Events').update(
    {
        _id: eventId,
        "groups._id": groupId,
        "groups.users._id": userId
    },

incorrect:
const result: any = await mongoose.model('Events').findOne(
    {
        _id: eventId,
        "groups._id": "5f270416e7964b20d6f8953e",
        "groups.$.users": { _id: '5f270877b4942d2528885dbd' }
    })
    // OR:
    {
        _id: eventId,
        "groups._id": "5f270416e7964b20d6f8953e",
        "groups.$.users._id" : '5f270877b4942d2528885dbd',  
    })

仅使用前两个谓词(eventId和组[$_id]),它将返回事件。但是第三个突破了。

有人知道为什么它返回null(直接从db复制对象id) 谢谢!

{
    "_id": ObjectId("5f270416e7964b20d6f8953d"),
    "lastRounds": [],
    "name": "EpicFest",
    "start": 1596392488896.0,
    "end": 1596392500896.0,
    "groups": [
      {
        "_id": ObjectId("5f270416e7964b20d6f8953e"),
        "name": "Vossius",
        "users": [
          {
            "created": 1596393590778.0,
            "sessionId": null,
            "feedBack": {
              "messagesSent": 0,
              "messagesSentLiked": 0,
              "messagesReceived": 0,
              "messagesReceivedLiked": 0,
              "userFeedbackReceived": [],
              "chatFeedbackReceived": [],
              "_id": ObjectId("5f270877b4942d2528885dbe")
            },
            "_id": ObjectId("5f270877b4942d2528885dbd"),
            "image": "someAvatr",
            "name": "hans",
            "groupId": "5f270416e7964b20d6f8953e",
            "results": []
          },
          
        ]
      },
      {
        "_id": ObjectId("5f270416e7964b20d6f8953f"),
        "users": [],
        "name": "Ignatius"
      }
    ],
    "results": [],
    "theses": [],
    "rounds": 10,
    "schedule": [],
    "__v": 4
}

2 个答案:

答案 0 :(得分:2)

使用聚合管道基于内部子文档获取。

在第一个比赛阶段,用eventId过滤并在内部groupId上进行$ elemMatch。 接下来,展开groupgroups.user

展开后,您将拥有一个扁平的对象结构,可以再次对其应用过滤器,现在就在groups.user._id上应用一个match阶段。

const pipeline = [
    {
        $match: {
            _id: eventId,
            groups: {
                $elemMatch: mongoose.Types.ObjectId('5f270416e7964b20d6f8953e')
            }
        }
    },
    {
        $unwind: '$groups'
    },
    {
        $unwind: '$groups.users'
    },
    {
        $match: {
            '$groups.users._id': mongoose.Types.ObjectId('5f270877b4942d2528885dbd')
        }
    }
];
const result: any = await mongoose.model('Events').aggregate(pipeline).exec();

答案 1 :(得分:1)

Mongo Play

db.collection.find({
  _id: ObjectId("5f270416e7964b20d6f8953d"),
  "groups._id": ObjectId("5f270416e7964b20d6f8953e"),
  "groups.users._id": ObjectId("5f270877b4942d2528885dbd")
})

您尝试使用字符串"5f270416e7964b20d6f8953e"。应该是ObjectId

您可以使用.表示法来访问嵌套元素或$elemMatch