MongoDB Join过滤器,输入,as,if,eq_id存在

问题描述 投票:0回答:1

2 个模式用户和卡

我将 user.catagories 存储在 user.catagory 下,以及与数组中列出的 catagory.cards 关联的卡片。 我将所有卡片数据存储在卡片架构中。 (见下文)

用户类别


    "catagory": [
        {
            "name": "test",
            "createdAt": "2024-02-01T21:47:34.215Z",
            "_id": "65bc1176cfb7da6997273ae3",
            "cards": [
                {
                    "_id": "65c43a9539206da4c953e334",
                    "createdAt": "2024-02-08T02:21:09.344Z",
                    "updatedAt": "2024-02-08T02:21:09.344Z",
                    "__v": 0
                },
                {
                    "_id": "65c43a9539206da4c953e32e",
                    "createdAt": "2024-02-08T02:21:09.344Z",
                    "updatedAt": "2024-02-08T02:21:09.344Z",
                    "__v": 0
                },
                {
                    "_id": "65c43a9539206da4c953e332",
                    "createdAt": "2024-02-08T02:21:09.344Z",
                    "updatedAt": "2024-02-08T02:21:09.344Z",
                    "__v": 0
                },
                {
                    "_id": "65d2447cbad1f058de61ecca",
                    "createdAt": "2024-02-18T17:55:08.414Z",
                    "updatedAt": "2024-02-18T17:55:08.414Z",
                    "__v": 0
                }
            ]
        },
        {
            "name": "baseball",
            "createdAt": "2024-02-01T23:12:46.996Z",
            "_id": "65bc256ecfb7da6997273c71",
            "cards": []
        },
    ],

卡数据

"cards": [
        {
            "_id": "65c43a9539206da4c953e334",
            "title": "PSA 9 1996 Topps Finest Gold w/ Coating #269 Kobe Bryant Rookie Card",
            "date": "2023-11-16T05:00:00.000Z",
            "price": 125000,
            "image": "s-l300.webp",
            "search": [],
            "createdAt": "2024-02-08T02:21:09.344Z",
            "updatedAt": "2024-02-08T02:21:09.344Z",
            "__v": 0
        },
        {
            "_id": "65c43a9539206da4c953e32e",
            "title": "1996-97 Topps Finest Bronze Refractor #74 Kobe Bryant (RC) PSA 7 W/ Coating",
            "date": "2024-02-01T05:00:00.000Z",
            "price": 130000,
            "image": "s-l300.webp",
            "search": [],
            "createdAt": "2024-02-08T02:21:09.344Z",
            "updatedAt": "2024-02-08T02:21:09.344Z",
            "__v": 0
        },
        {
            "_id": "65c43a9539206da4c953e332",
            "title": "1996-97 Fleer Ultra Series 2 Basketball Factory Sealed Hobby Box-Kobe Bryant RC?",
            "date": "2023-11-28T05:00:00.000Z",
            "price": 124999,
            "image": "s-l300.webp",
            "search": [],
            "createdAt": "2024-02-08T02:21:09.344Z",
            "updatedAt": "2024-02-08T02:21:09.344Z",
            "__v": 0
        },
        {
            "_id": "65d2447cbad1f058de61ecca",
            "title": "HUGE SPORTS CARD COLLECTION! 2023 CJ Stroud Justin Herbert Rookie Auto RPA READ",
            "date": "2024-02-17T05:00:00.000Z",
            "price": 75000,
            "image": "s-l300.webp",
            "search": [],
            "createdAt": "2024-02-18T17:55:08.414Z",
            "updatedAt": "2024-02-18T17:55:08.414Z",
            "__v": 0
        }
    ]

合计: 这段代码让我非常接近我想要的。但是,它附加结果卡数组并覆盖 catagory.cards 数组,而不是仅基于 'users.catagory.cards._id' === 'cards._id' 进行更新。

const results = await User.aggregate(
  [
    {
      $lookup: {
        from: 'cards',
        localField: 'catagory.cards',
        foreignField: '_id',
        as: 'cards'
      }
    },
    {
      $addFields: { 'catagory.cards': '$cards' }
    }
  ],
  { maxTimeMS: 60000, allowDiskUse: true }
);

我尝试使用过滤器,但没有成功。

{
  "catagory.cards": {
            $filter: {
               input: "$catagory.cards",
               as: "card",
               cond: { $in: [ "$$card._id", "$catagory.cards"] }
            }
         }
}
mongodb filter left-join inner-join aggregation
1个回答
0
投票

首先很高兴看到这个问题——您到底想要实现什么。现在,让我尝试一些猜测,并告诉我是否有帮助。否则请提供更具体的期望,以便我更新答案。

我注意到的第一件事是 $lookup 中的示例中的

localField
'catagory.cards'
,而它应该是
'catagory.cards._id'
,因为您仅通过
_id
字段匹配,而不是整个记录。 另外,注意到一个拼写错误“类别”而不是“类别”。如果不是故意的 - 请小心,因为如果您在代码的其他部分编写
category
,这可能是某些问题的根源。

现在让我猜您想查看

category.cards
字段的数组项内的所有卡片详细信息。

可以通过以下方式实现:

  • $unwind
    -将数组放入单独的记录中(我们必须将类别展开到单独的记录中,以便在每个记录中包含每个类别,然后展开类别卡以使每个卡在单独的记录中),
  • 然后通过
    $lookup
    将它们与卡片详细信息匹配到
    category.cards
    字段(这样它将覆盖每个记录的该字段 - 这就是为什么每个类别卡都有每个记录很重要),
  • 然后再次将这些记录组合回一条记录(通过按类别分组,然后按 null 分组以得到我们最初拥有的一条记录):
db.User.aggregate([
    { $unwind: {
        path: '$catagory',
        preserveNullAndEmptyArrays: true
    }}, 
    { $unwind: {
        path: '$catagory.cards',
        preserveNullAndEmptyArrays: true
    }}, 
    { $lookup: {
        from: 'cards',
        localField: 'catagory.cards._id',
        foreignField: '_id',
        as: 'catagory.cards'
    }},
  { $group: {
      _id: '$catagory._id',
      userId: { $first: '$_id' },
      categoryId: { $first: '$catagory._id' },
      name: { $first: '$catagory.name' },
      createdAt: { $first: '$catagory.createdAt' },
      cards: { $push: { $arrayElemAt: ['$catagory.cards', 0] } }
  }},
  { $group: {
      _id: '$userId',
      catagory: { $addToSet: {
          _id: '$categoryId',
          name: '$name',
          createdAt: '$createdAt',
          cards: '$cards'
      }},
  }},
]);

我尝试了它,它为我提供了以下输出:

{
    "_id" : ObjectId("65d3d362c2006d4572b028a3"),
    "catagory" : [
        {
            "_id" : "65bc1176cfb7da6997273ae3",
            "name" : "test",
            "createdAt" : "2024-02-01T21:47:34.215Z",
            "cards" : [
                {
                    "_id" : "65c43a9539206da4c953e334",
                    "title" : "PSA 9 1996 Topps Finest Gold w/ Coating #269 Kobe Bryant Rookie Card",
                    "date" : "2023-11-16T05:00:00.000Z",
                    "price" : NumberInt(125000),
                    "image" : "s-l300.webp",
                    "search" : [

                    ],
                    "createdAt" : "2024-02-08T02:21:09.344Z",
                    "updatedAt" : "2024-02-08T02:21:09.344Z",
                    "__v" : NumberInt(0)
                },
                {
                    "_id" : "65c43a9539206da4c953e32e",
                    "title" : "1996-97 Topps Finest Bronze Refractor #74 Kobe Bryant (RC) PSA 7 W/ Coating",
                    "date" : "2024-02-01T05:00:00.000Z",
                    "price" : NumberInt(130000),
                    "image" : "s-l300.webp",
                    "search" : [

                    ],
                    "createdAt" : "2024-02-08T02:21:09.344Z",
                    "updatedAt" : "2024-02-08T02:21:09.344Z",
                    "__v" : NumberInt(0)
                },
                {
                    "_id" : "65c43a9539206da4c953e332",
                    "title" : "1996-97 Fleer Ultra Series 2 Basketball Factory Sealed Hobby Box-Kobe Bryant RC?",
                    "date" : "2023-11-28T05:00:00.000Z",
                    "price" : NumberInt(124999),
                    "image" : "s-l300.webp",
                    "search" : [

                    ],
                    "createdAt" : "2024-02-08T02:21:09.344Z",
                    "updatedAt" : "2024-02-08T02:21:09.344Z",
                    "__v" : NumberInt(0)
                },
                {
                    "_id" : "65d2447cbad1f058de61ecca",
                    "title" : "HUGE SPORTS CARD COLLECTION! 2023 CJ Stroud Justin Herbert Rookie Auto RPA READ",
                    "date" : "2024-02-17T05:00:00.000Z",
                    "price" : NumberInt(75000),
                    "image" : "s-l300.webp",
                    "search" : [

                    ],
                    "createdAt" : "2024-02-18T17:55:08.414Z",
                    "updatedAt" : "2024-02-18T17:55:08.414Z",
                    "__v" : NumberInt(0)
                }
            ]
        },
        {
            "_id" : "65bc256ecfb7da6997273c71",
            "name" : "baseball",
            "createdAt" : "2024-02-01T23:12:46.996Z",
            "cards" : [

            ]
        }
    ]
}

如果这是您想要实现的结果,如果您有任何疑问或希望获得任何进一步的说明,请告诉我。

欢迎光临!

© www.soinside.com 2019 - 2024. All rights reserved.