暂无图片
暂无图片
3
暂无图片
暂无图片
暂无图片

文档型数据库解读13:文档型数据库建模之{属性模式}

巨杉数据库 2024-10-16
375

随着数据多样性和复杂性的增加,文档型数据库的建模需求变得更为灵活。在这个背景下,{属性模式}(Attribute Pattern)作为文档模型的一项强大特性,为处理具有不同特征的对象提供了有效的解决方案。本文将深入解析{属性模式},介绍其总体概念、变体以及详细实现步骤。

{属性模式}总体介绍

{属性模式}的出发点在于,当无法预测对象之间的差异性,同时又需要对这些字段进行查询时,如何更有效地建模和索引。传统关系型数据库通常使用属性表来转置不可预测的列,在「巨杉文档型数据库」中可以通过{属性模式}来进行更加清晰的建模。

{属性模式}的核心思想是将多个字段组合成一个索引,使得在创建索引时即包含未来可能使用的其他未知字段。这对于存放目录类型的应用尤为便利,能够提升对这些字段进行搜索的效率。

如何实现{属性模式}

在传统的关系型数据库中,使用属性表将未定义的列进行存放。在文档型数据库中,采用{属性模式}时,文档中的属性名称和属性值分别以"k"和"v"的形式组合,形成一个数组。这样生成的文档,允许查询时对无法预知的属性名称生成索引以提升查询性能,但相较于常规JSON文档增加了理解的难度。

{属性模式}的实现需要遵循以下步骤:

  1. 确定目标字段: 确定要组合在一起的字段,创建一个数组来包含这些字段。

  2. 创建子文档: 对每个目标字段,在数组中创建一个子文档,使用"k"表示字段名称,"v"表示字段的值。

  3. 处理额外的限定符: 对于额外的限定符(如q1、q2等),使用额外的字段将这些值绑定。大多数目标字段应具有一致的额外字段。

  4. 创建复合索引: 使用所有字段(k、v、q1、q2等)创建一个复合索引。

例如,以下文档中表示价格的字段最初如下所示。

    {
    "_id": "12345"
    "name": "NoSQL数据建模及模型设计"
    ...
    "price_china": Decimal(68.00)
    "price_usa": Decimal(9.99)
    }

    应用{属性模式}后,它们如下所示:

      {
      "_id": "12345"
      "name": "NoSQL数据建模及模型设计"
      "prices": [
      {
      "k": "price_china"
      "v": Decimal(68.00),
      "q": "RMB"
      },
      {
      "k": "price_usa"
      "v": Decimal(9.00),
      "q": "USD"
      }
      ]
      }


      使用{属性模式}的IoT物联网设备管理示例

      在IoT物联网设备管理的场景中,为了实现对IoT物联网设备搜索字段的建模,我们选择使用{属性模式}。这种模式允许我们对用于搜索的字段进行建模,同时避免为每个搜索条件创建独立索引。搜索页面提供下拉菜单,通过在details字段下分组属性,使用通配符索引来实现。以下是IoT设备文档的示例:

        // 带有属性的宠物文档 
        {
        "_id": "dev749427",
        "dev_name": "Wind Sensor (Model-4)",
        "details": [
        "area": "area6685",
        "speed": 3.5, // 米/秒
        "temperature": 28.3, // 摄氏度
        "humidity": 73, // %
        "altitude": 65 // 米
        ]
        }

        在「巨杉文档型数据库」中,为了提升查询性能,可以创建“通配符索引(Wildcard Index)”,执行语句如下。

          db.pets.createIndex({ "details.$**": 1 });

          但特别需要注意的是,并非所有文档型数据库都提供“通配符索引”特性,而且在某些情况下其性能可能不如理想。

          因此,如果您所使用的版本不支持“通配符索引”特性,或遇到性能问题。可以尝试使用{属性模式},将属性进行转置后的文档如下:

            {
            "_id": "dev749427",
            "dev_name": "Wind Sensor (Model-4)",
            "details": [
            { "k": "area", "v": "area6685" },
            { "k": "speed", "v": 3.5, "q": "米/秒" },
            { "k": "temperature", "v": 28.3, "q": "摄氏度" },
            { "k": "humidity", "v": 73, "q": "%" },
            { "k": "altitude", "v": 65, "q": "米" }
            ]
            }

            接着,可以创建多键索引:

              db.iotdevs.createIndex({ "details.k": 1, "details.v": 1, "details.q": 1 });

              最后,通过以下查询找到深绿色的宠物:

                db.iotdevs.find({ details: { $elemMatch: { "k""area""v""area6685" }}});

                {属性模式}的灵活性使得在不同搜索条件下的建模更为便捷。通过转置属性,可以轻松构建适用于多种情况的查询,而无需额外索引。这种模式在实现搜索功能时具有高度的可扩展性,为项目提供了更好的查询效率和维护性。


                {属性模式}的优点

                1. 如果由于大量字段导致索引过多,{属性模式}将有助于降低复杂性并简化数据库管理。

                2. {属性模式}允许这些新属性自动添加为组中所有属性的索引的一部分,而无需关注文档中的新字段为其创建索引。


                {属性模式}的局限

                1. 由于{属性模式}的结构和文档的其他部分所使用的键值表示方法截然不同,文档结构的可读性会下降。

                2. 在同一子文档中查询多个字段时,必须指示文档型数据库使用$elemMatch。否则,在没有此关键字的情况下查询两个字段将返回任意一个匹配第一个条件的子文档,和匹配第二个条件的第二个子文档的数据。


                总结

                问题

                • 文档中有许多不可预测的键需要建立索引。

                解决方案

                • 将字段重新排列为键-值对。

                使用案例

                • 产品特征。

                • 相同值类型的一组字段。

                优点

                • 降低索引数量。

                • 允许通过索引自动考虑新的键名称。

                局限

                • k-v符号法与文档中其他字段不同,可读性较差。

                • 查询必须在字段子句之间使用$elemMatch操作符。


                文章转载自巨杉数据库,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                评论