代码之家  ›  专栏  ›  技术社区  ›  Sylith

你能在另一个文档中使用MongoDB文档ID作为密钥吗?

  •  0
  • Sylith  · 技术社区  · 1 年前

    我正试图在MongoDB Atlas中为一个电子商务应用程序实现一个购物车集合,我不确定引用用户购物车中单独集合中的产品的正确方式。

    我可以使用产品的文档id作为购物车文档中的密钥吗?即。

    cart = {
       productID1: productQty1,
       productID2: productQty2,
       ...
    }
    

    或者我需要做这样的事情:

    cart = [
       {
        productID: productID1,
        qty: productQty1,
       },
       {
        productID: productID2,
        qty pro
       },
       ...
    ]
    
    

    其中productID1是产品集合中对应产品文档的_id?

    由于_id的类型是ObjectID,我不确定是否可以/应该将其用作字符串类型的键,或者使用docID作为键而不是值是否存在潜在问题。

    0 回复  |  直到 1 年前
        1
  •  0
  •   jQueeny    1 年前

    如果你自己做(即没有Mongoose这样的对象建模库),你的第二个选择是最有利的设计。根据 docs 手册参考:

    手动参考是将一个文档的_id字段包含在另一个文档中的做法。然后,应用程序可以根据需要发出第二个查询来解析引用的字段。

    例如:

    db.products.findOne(); // Find first item in products collection
    // Returns
    {
       _id: ObjectId("64f8cd127f6c107e984014fc"),
       name: 'Hat',
    }
    
    db.users.findOne({ _id : ObjectId("64f8cbb87f6c107e984014f5")}); // Find a user by their _id
    // Returns
    {
       _id: ObjectId("64f8cbb87f6c107e984014f5"),
       first_name: 'Bob',
       last_name: 'Smith',
       address: '123 Tree Lane'
    }
    
    db.carts.findOne({ user_id : ObjectId("64f8cbb87f6c107e984014f5") }); // Find a cart by user_id
    // Returns
    {
       _id: ObjectId("64f8cd507f6c107e984014ff"),
       product_id: ObjectId("64f8cd127f6c107e984014fc"), // Hat
       user_id: ObjectId("64f8cbb87f6c107e984014f5") // Bob
    }
    

    然后,您可以执行 $lookup 以联接类似于SQL中的左联接的文档。

    db.carts.aggregate([
      { $match: { user_id: ObjectId("64f8cbb87f6c107e984014f5") } }, // Find Bob's cart
      {
        $lookup: // Now lookup Bob's details and add them as "user_details"
          {
            from: "users",
            localField: "user_id",
            foreignField: "_id",
            as: "user_details"
          }
       }
    ])
    // Returns
    [
       {
          _id: ObjectId("64f8cd507f6c107e984014ff"),
          product_id: ObjectId("64f8cd127f6c107e984014fc"),
          user_id: ObjectId("64f8cbb87f6c107e984014f5"),
          user_details: [
             {
                _id: ObjectId("64f8cbb87f6c107e984014f5"),
                first_name: 'Bob',
                last_name: 'Smith',
                address: '123 Tree Lane'
             }
          ]
       }
    ]
    

    这使得管理数据基于 _id 易于管理。

    然而,这非常像关系数据库的设计,MongoDB是NoSQL,因此它是专门为利用在彼此中存储文档而设计的。我建议你读一下 embedded documents 并尽可能使用它们。

    你的 cart 可以存储的数组 product_id 就像这样:

    db.carts.findOne({ user_id : ObjectId("64f8cbb87f6c107e984014f5") }); // Find a cart by user_id
    // Returns
    {
      _id: ObjectId("64f8cd507f6c107e984014ff"),
      products:[
         { product_id: ObjectId("64f8cd127f6c107e984014fc") }, // Hat,
         { product_id: ObjectId("64f8d35c7f6c107e98401512") } // Something else
      ],
      user_id: ObjectId("64f8cbb87f6c107e984014f5") // Bob
    }
    

    然后,如果你想在中加入产品详细信息,你可以这样做:

    db.carts.aggregate([
      { $match: { user_id: ObjectId("64f8cbb87f6c107e984014f5") } }, // Find Bob's cart
      {
        $lookup: // Now lookup the product details add them as "product_details"
          {
            from: "products",
            localField: "products.product_id",
            foreignField: "_id",
            as: "product_details"
          }
       }
    ])
    // Returns
    [
       {
          _id: ObjectId("64f8cd507f6c107e984014ff"),
          user_id: ObjectId("64f8cbb87f6c107e984014f5"),
          products: [
             { product_id: ObjectId("64f8cd127f6c107e984014fc") },
             { product_id: ObjectId("64f8d35c7f6c107e98401512") }
          ],
          product_details: [
             { _id: ObjectId("64f8cd127f6c107e984014fc"), name: 'Hat' },
             { _id: ObjectId("64f8d35c7f6c107e98401512"), name: 'Shoe' }
          ]
       }
    ]