在MongoDB中仅存储/保存对象列表中的特定对象沿着父对象

nwnhqdif  于 2023-02-21  发布在  Go
关注(0)|答案(1)|浏览(102)
    • bounty将在6天后过期**。回答此问题可获得+50声望奖励。jarvo69希望引起更多人关注此问题。

在mongodb中,我有一个名为category sample data的主表,如下所示:

{
    "_id" : "63d3e01f43aa4e0ee349f841",
    "subCategories" : [
        {
            "subCategoryId" : NumberLong(1), 
            "name": "Mobile phones" 
        },
        {
            "subCategoryId" : NumberLong(2), 
            "name": "XYZ Machine" 
        }
    ]
}

还有一个表product,示例数据如下:

{
    "_id" : "63d3e13b43aa4e0ee349f842",
    "productId" : NumberLong(1),
    "name" : "iphone 14",
    "category" : DBRef("category", "63d3e01f43aa4e0ee349f841")
}

在添加新产品时,只能从所选类别中选择1个类别和1个子类别。在我的例子中,我使用@DbRef,我正在努力寻找一种方法,通过这种方法,我只能在产品表中保存1个子类别。现在它指向类别表的整个对象,其中可以有x个子类别
是否可以使用@DbRef注解来实现这一点,而不更改数据库结构,也不破坏单独的类别表和子类别表之间的类别表记录?
可能是这样的:

{
    "_id" : "63d3e13b43aa4e0ee349f842",
    "productId" : NumberLong(1),
    "name" : "iphone 14",
    "category" : DBRef({"category", "63d3e01f43aa4e0ee349f841"},
                       "subCategoryId", 1)

}

使用MongoDb版本4+和Java spring-data-mongo

blmhpbnm

blmhpbnm1#

我认为不改变模式是不可能实现你所期望的行为的。
DBRef是表示文档的约定,而不是特定的引用类型。
因此DBRef将指向特定的文档,而不是某个子文档数组条目。
这给我们留下了两个选择:
1.更改category集合以存储文档,如下所示:

{
    "categoryId" : "63d3e01f43aa4e0ee349f841", // this is new
    "subCategoryId" : NumberLong(1), 
    "name": "Mobile phones" 
}

遗憾的是,由于不允许更改架构,因此禁止此操作
1.在product架构中添加另一个字段以存储子类别ID,并在$lookup

{
      "_id": "63d3e13b43aa4e0ee349f842",
      "productId": NumberLong(1),
      "name": "iphone 14",
      "category": {
        "$ref": "category",
        "$id": "63d3e01f43aa4e0ee349f841"
      },
      "subCategoryId": NumberLong(1) // this is new
    }

汇总:

db.product.aggregate([
  {
    $match: {
      "_id": "63d3e13b43aa4e0ee349f842"
    }
  },
  {
    "$lookup": {
      "from": "category",
      "let": {
        categoryId: "$category.$id",
        subCategoryId: "$subCategoryId"
      },
      "pipeline": [
        {
          $match: {
            $expr: {
              $eq: [
                "$$categoryId",
                "$_id"
              ]
            }
          }
        },
        {
          $unwind: "$subCategories"
        },
        {
          $match: {
            $expr: {
              $eq: [
                "$$subCategoryId",
                "$subCategories.subCategoryId"
              ]
            }
          }
        }
      ],
      "as": "subCategoryLookup"
    }
  }
])

Mongo Playground
这也是禁止的,因为它需要向product模式中再添加一个字段,但我仍然建议这样做,因为这只涉及对模式的最小更改。

相关问题