【问题标题】:Mongo data modeling for monitoring application用于监控应用的 Mongo 数据建模
【发布时间】:2018-09-24 20:30:51
【问题描述】:

我正在尝试了解监控应用程序的最佳建模方式。

我有一个监控应用程序,它将每 30 分钟运行一次,以从目标系统获取统计信息并将详细信息存储在 MongoDB 中。

用例:

产品、公司

将有大约 2000 种产品。产品将被添加/删除,但每个月的增长不会超过 10%。所以,我预计未来 1 年不会超过 3000 个。

公司是每种产品的消费者。每个产品将有 1 到 10 家公司在使用该产品。消费者数量也会上下浮动。

因此,在每次运行时,我们都会获得产品列表以及相应的公司。产品详情会像,

产品:

  1. 产品名称
  2. 总数(这将提供当前可用的数字,并且每次投票都会改变)
  3. 产品重量
  4. 耐用天数(可能会不时改变)
  5. 公司列表 - 谁在使用此产品

产品样本数据:

{
            "productName" : "Small Box",
            "total" : NumberLong(1000),
            "weight" : "1.5",
            "durability" : "20",
            "companies" : [
                {
                    "name" : "Nike",
                    "taken" : NumberLong(10)
                },
                {
                    "name" : "Reebok",
                    "taken" : NumberLong(20)
                }
            ]
}

在这里,每次投票时的计数都会不断变化。

网络应用程序:

将有 3 个屏幕显示详细信息。

  1. 仪表板 - 将显示高级统计信息,例如(产品数量、公司数量、总规模......)
  2. 产品 - 列表视图(查看完整列表)- 将在选择任何产品时显示产品的详细信息

    在这里,我必须显示产品详细信息,并且必须列出所有正在消费的公司。

  3. 公司 - 列表视图(查看完整列表)- 将显示每个选择任何公司的详细公司

    在这里,我必须显示公司的详细信息以及它正在消费的所有产品。

顺便说一下,我目前正在存储。

  1. 仪表板集合 - 显示统计详细信息,例如产品总数、公司总数……

    { “时间” : "totalProducts" : NumberLong(1000), “totalCompanies”:“1.5”, }

  2. 产品集合 - 将包含以下详细信息。

{
                "productName" : "Small Box",
                "total" : NumberLong(1000),
                "weight" : "1.5",
                "durability" : "20",
                "companies" : [
                    {
                        "name" : "Nike",
                        "taken" : NumberLong(10)
                    },
                    {
                        "name" : "Reebok",
                        "taken" : NumberLong(20)
                    }
                ]
    }
  1. 公司集合 - 将包含以下详细信息
{
            "companyName" : "Nike",
            "products" : [
                {
                    "name" : "Small Box",
                    "taken" : NumberLong(10)
                },
                {
                    "name" : "Medium Box",
                    "taken" : NumberLong(20)
                }
            ] 
}

因此,在每次运行时,我都会生成唯一的 ID,并将此 ID 添加到所有正在存储的数据中。我在这些集合中只保留最后 2 周的数据。超过 2 周的数据将每天清理。

因此,当用户来到仪表板时,进行排序以获取最新记录并显示详细信息。 Dashboard 集合中的每次运行只有一条记录,并且会有最近 2 周的记录。

当用户进入 Products 屏幕时,仍然必须从 Dashboard 获取最新记录以获取 UniqueId,然后转到 Products 集合以获取该 UniqueId 的所有记录,因为每次运行将有大约 2000 条记录。公司收藏也是如此。

在这里,我必须始终显示最新数据。当用户进入产品或公司屏幕时,我将选择 2 个不同的集合。

有没有更好的方法?

【问题讨论】:

    标签: mongodb


    【解决方案1】:

    请查看它可以帮助您如何准备架构 注意:Mongo 版本:3.6.5

    产品冷却

    /* 1 */
    {
        "_id" : ObjectId("5bb1e270269004e06093e178"),
        "productName" : "Small Box",
        "total" : NumberLong(1000),
        "weight" : "1.5",
        "durability" : "20",
        "companies" : [ 
            ObjectId("5bb1e2d2269004e06093e17b"), 
            ObjectId("5bb1e2d8269004e06093e17c")
        ],
        "date" : ISODate("2018-10-01T09:28:40.502Z")
    }
    
    /* 2 */
    {
        "_id" : ObjectId("5bb1e293269004e06093e179"),
        "productName" : "Large Box",
        "total" : 1000.0,
        "weight" : "1.2",
        "durability" : "20",
        "companies" : [ 
            ObjectId("5bb1e2d8269004e06093e17c"), 
            ObjectId("5bb1e2de269004e06093e17d")
        ],
        "date" : ISODate("2018-10-01T09:28:40.502Z")
    }
    
    /* 3 */
    {
        "_id" : ObjectId("5bb1e29d269004e06093e17a"),
        "productName" : "Medium Box",
        "total" : 1000.0,
        "weight" : "1.2",
        "durability" : "20",
        "companies" : [ 
            ObjectId("5bb1e2d2269004e06093e17b"), 
            ObjectId("5bb1e2d8269004e06093e17c"), 
            ObjectId("5bb1e2de269004e06093e17d")
        ],
        "date" : ISODate("2018-07-01T09:28:40.502Z")
    }
    

    公司合集

    /* 1 */
    {
        "_id" : ObjectId("5bb1e2d2269004e06093e17b"),
        "companyName" : "Nike"
    }
    
    /* 2 */
    {
        "_id" : ObjectId("5bb1e2d8269004e06093e17c"),
        "companyName" : "Reebok"
    }
    
    /* 3 */
    {
        "_id" : ObjectId("5bb1e2de269004e06093e17d"),
        "companyName" : "PUMA"
    }
    

    通过公司获取单品

    db.getCollection('products').aggregate([{
          $match :  { "_id" : ObjectId("5bb1e270269004e06093e178") } },
           { $lookup : {
               from : 'company',
               foreignField : '_id',
               localField : 'companies',
               as : 'companies'
               }
           }
          ])
    

    所有带有公司列表的产品

    db.getCollection('products').aggregate([
           { $lookup : {
               from : 'company',
               foreignField : '_id',
               localField : 'companies',
               as : 'companies'
               }
           }
          ])
    

    公司编号及其二手产品

      db.getCollection('company').aggregate([{
              $match :  { "_id" : ObjectId("5bb1e2d2269004e06093e17b") } },
               { $lookup : {
                   from : 'products',
                   foreignField : 'companies',
                   localField : '_id',
                   as : 'products'
                   }
               }
              ])
    

    还可以通过在每个产品中添加日期字段来获得上周数据

        db.getCollection('products').aggregate([{
              $match :  { 
                  date: {
                    $gte: new Date(new Date() - 7 * 60 * 60 * 24 * 1000)
            } } },
               { $lookup : {
                   from : 'products',
                   foreignField : 'companies',
                   localField : '_id',
                   as : 'products'
                   }
               }
        ])
    

    与公司一起获取最新产品

    db.getCollection('products').aggregate([
           { $sort : { date : -1} },
           { $limit : 1},
           { $lookup : {
               from : 'company',
               foreignField : '_id',
               localField : 'companies',
               as : 'companies'
               }
           }
          ])
    

    【讨论】:

    • 是否需要先从Product中查询ID?如果我需要获取所有公司的副产品(只有一个)的最新日期怎么办?我可以单独查询吗?
    • 我已经更新了我的答案。请检查并告诉我它对你有用。
    【解决方案2】:

    因此,在每次运行时,我都会生成唯一的 ID 并将此 ID 添加到所有存储的数据中。我在这些集合中只保留最后 2 周的数据。超过 2 周的数据将每天清理。

    我不会这样做。我会使用_id,mongodb自动给你。并制作一个收集所有这些对象 id 的 runobject。因为每个对象有 1 个键比 336 个键更好(48(每天 30 分钟)x 14(2 周内的天数))

    我会创建一个包含 company_id、product_id 和时间戳数组的运行对象。如果在 30 分钟内没有任何变化,那么我将有可能只使用 runobject _id(第一个相同的)和时间戳。所以你节省了很多空间。

    希望我能正确理解你,因为这对我来说很难读。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-25
      • 2011-01-19
      • 1970-01-01
      • 2011-09-25
      • 2010-10-15
      相关资源
      最近更新 更多