如何为此设计架构?

时间:2019-11-22 13:33:39

标签: javascript node.js mongodb express mongoose

我正在开发MERN应用。我需要为相当简单的移动商店网站设计架构。

数据应采用以下格式

    {
  [
    "IOS":[
      "Apple":[
        {
          "model":"Iphone6"
        },
        {
          "model":"Iphone7"
        }
      ]
    ],
    "Android":[
      "Samsung":[
        {
          "model":"S6"
        },
        {
          "model":"S7"
        }
      ],
      "OnePlus":[
        {
          "model":"oneplu6"
        },
        {
          "model":"onplus7"
        }
      ]
    ],
    "Windows":[
      "Nokia":[
        {
          "model":"Nokia 7.2"
        }
      ]
    ]
  ]
}

如何在mongo / mongoose中为此设计方案?

1 个答案:

答案 0 :(得分:1)

如果不需要使用操作系统和品牌名称作为密钥,那么我有这样的解决方案。

我将这样设置我的模式:

const mongoose = require("mongoose");

const operatingSystemSchema = new mongoose.Schema({
  name: {
    type: String,
    required: true
  }
});

const brandSchema = new mongoose.Schema({
  name: {
    type: String,
    required: true
  }
});

const productSchema = new mongoose.Schema({
  model: {
    type: String,
    required: true
  },
  operatingSystem: {
    type: mongoose.Schema.Types.ObjectId,
    ref: "OperatingSystem"
  },
  brand: {
    type: mongoose.Schema.Types.ObjectId,
    ref: "Brand"
  }
});

module.exports = {
  OperatingSystem: mongoose.model("OperatingSystem", operatingSystemSchema),
  Brand: mongoose.model("Brand", brandSchema),
  Product: mongoose.model("Product", productSchema)
};

根据架构插入文档后,我们可以使用以下汇总对操作系统和品牌进行分组:

db.products.aggregate([
  {
    $lookup: {
      from: "operatingsystems",
      localField: "operatingSystem",
      foreignField: "_id",
      as: "operatingSystems"
    }
  },
  {
    $lookup: {
      from: "brands",
      localField: "brand",
      foreignField: "_id",
      as: "brands"
    }
  },
  {
    $unwind: "$operatingSystems"
  },
  {
    $unwind: "$brands"
  },
  {
    $replaceRoot: {
      newRoot: {
        $mergeObjects: [
          "$$ROOT",
          {
            operatingSystem: "$operatingSystems.name",
            brand: "$brands.name"
          }
        ]
      }
    }
  },
  {
    $project: {
      brands: 0,
      operatingSystems: 0
    }
  },
  {
    $group: {
      _id: {
        "operatingSystem": "$operatingSystem",
        "brand": "$brand",

      },
      products: {
        $push: "$$ROOT"
      }
    }
  },
  {
    $group: {
      "_id": "$_id.operatingSystem",
      "data": {
        "$push": {
          "brand": "$_id.brand",
          "models": "$products.model"
        }
      }
    }
  },
  {
    $project: {
      "OS": "$_id",
      "_id": 0,
      "data": 1
    }
  }
])

Playground

以及快递方的示例路线:

router.get("/", async (req, res) => {
  const result = await Product.aggregate([
    {
      $lookup: {
        from: "operatingsystems",
        localField: "operatingSystem",
        foreignField: "_id",
        as: "operatingSystems"
      }
    },
    {
      $lookup: {
        from: "brands",
        localField: "brand",
        foreignField: "_id",
        as: "brands"
      }
    },
    {
      $unwind: "$operatingSystems"
    },
    {
      $unwind: "$brands"
    },
    {
      $replaceRoot: {
        newRoot: {
          $mergeObjects: [
            "$$ROOT",
            {
              operatingSystem: "$operatingSystems.name",
              brand: "$brands.name"
            }
          ]
        }
      }
    },
    {
      $project: {
        brands: 0,
        operatingSystems: 0
      }
    },
    {
      $group: {
        _id: {
          operatingSystem: "$operatingSystem",
          brand: "$brand"
        },
        products: {
          $push: "$$ROOT"
        }
      }
    },
    {
      $group: {
        _id: "$_id.operatingSystem",
        data: {
          $push: {
            brand: "$_id.brand",
            models: "$products.model"
          }
        }
      }
    },
    {
      $project: {
        OS: "$_id",
        _id: 0,
        data: 1
      }
    }
  ]);

  res.send(result);
});

结果将如下所示:

[
  {
    "OS": "Windows",
    "data": [
      {
        "brand": "Nokia",
        "models": [
          "Nokia 7.2"
        ]
      }
    ]
  },
  {
    "OS": "Android",
    "data": [
      {
        "brand": "OnePlus",
        "models": [
          "oneplus7",
          "oneplu6"
        ]
      },
      {
        "brand": "Samsung",
        "models": [
          "S7",
          "S6"
        ]
      }
    ]
  },
  {
    "OS": "IOS",
    "data": [
      {
        "brand": "Apple",
        "models": [
          "Iphone7",
          "Iphone6"
        ]
      }
    ]
  }
]