使用属性模式对数据进行分组
属性模式是一种模式设计模式,可帮助组织具有许多相似字段的文档,尤其是当字段股票共同特征时。如果需要对相似字段的这些子集进行排序或查询,属性模式可以优化您的模式。它通过将每个文档的多个相似字段合并到一个键值子文档中,创建更轻松的文档索引。通过属性模式,您无需对多个相似字段创建多个索引,只需创建更少的索引,从而更快、更简单地写入查询。
如果您的集合应用以下任一条件,请使用属性模式:
您有大型文档,其中包含许多具有共同特征的相似字段,您想要对这些大型文档进行排序或查询。
一小部分文档包含排序所需的字段。
关于此任务
以一集合电影为例。集合中的典型文档可能如下所示:
db.movies.insertOne( { "_id": 1, "title": "Star Wars", "runtime": 121, "directors": ["George Lucas"], release_US: ISODate("1977-05-20T01:00:00+01:00"), release_France: ISODate("1977-10-19T01:00:00+01:00"), release_Italy: ISODate("1977-10-20T01:00:00+01:00"), release_UK: ISODate("1977-12-27T01:00:00+01:00") } )
请注意上述文档中不同国家/地区的多个发布日期字段。如果要搜索发布日期,则必须同时查看许多字段。如果没有属性模式,则需要在 movies
集合上创建多个索引,才能快速搜索发布日期:
db.movies.createIndex({ release_US: 1 }); db.movies.createIndex({ release_France: 1 }); db.movies.createIndex({ release_Italy: 1 }); db.movies.createIndex({ release_UK: 1 });
但是,索引成本高昂,并且可能会降低性能,尤其是对于写入操作。以下过程演示了如何将不同发布日期的信息子集移入大量,从而减少索引需求,从而将属性模式应用movies
集合。
步骤
将数据子集分组到一个大量中。
重新组织模式,将各种发布日期字段转换为键值对大量:
db.movies.insertOne( { "_id": 1, "title": "Star Wars", "runtime": 121, "directors": ["George Lucas"], releases: [ { location: "USA", date: ISODate("1977-05-20T01:00:00+01:00") }, { location: "France", date: ISODate("1977-10-19T01:00:00+01:00") }, { location: "Italy", date: ISODate("1977-10-20T01:00:00+01:00") }, { location: "UK", date: ISODate("1977-12-27T01:00:00+01:00") } ] } )
结果
如果文档有多个字段追踪相同或相似的特征,则属性模式可以避免在每个相似字段上创建索引。通过将相似字段合并到一个大量中并在该大量上创建索引,可以减少所需索引的总数并提高查询性能。
其他使用案例
当文档描述项目的特征时,属性模式会很有帮助。某些产品(例如服装)的尺寸可能会以小号、中号或大号表示。同一集合中的其他产品可能会用体积表示,而其他产品可能会以物理尺寸或重量表示。
示例,考虑集合瓶装水。不使用属性模式的文档可能如下所示:
db.bottles.insertOne([ { "_id": 1, "volume_ml": 500, "volume_ounces": 12 } ])
以下代码将属性模式应用于 bottles
集合:
db.bottles.insertOne([ { "_id": 1, specs: [ { k: "volume", v: "500", u: "ml" }, { k: "volume", v: "12", u: "ounces" }, ] } ])
由于第一个文档中的 volume_ml
和 volume_ounces
字段包含相似信息,因此上面的模式将它们合并到一个字段specs
中。 specs
字段将有关给定水瓶的测量规格的信息分组在一起,其中 k
字段指定测量的内容,v
指定值,u
指定测量单位。
属性模式还允许您将具有不同名称的相似字段群组在一起。通过键值对指定属性(例如指定测量内容的 k
字段),您可以将更多种类的相似字段存储到一个大量中,从而最大限度地减少高效查询数据所需的索引数量。
示例,考虑 bottles
集合中不使用属性模式的此文档。该文档存储有关水瓶体积和高度的规范:
db.bottles.insertOne([ { "_id": 1, "volume_ml": 500, "volume_ounces": 12, "height_inches": 8 } ])
以下代码将属性模式应用于文档。它将 volume_ml
、volume_ounces
和 height_inches
字段分组到 specs
大量中:
db.bottles.insertOne([ { "_id": 1, specs: [ { k: "volume", v: "500", u: "ml" }, { k: "volume", v: "12", u: "ounces" }, { k: "height", v: "8", u: "inches" } ] } ])
使用键值对(例如 k
、v
和 u
)可以更灵活地向大量添加哪些字段。可以合并到大量中的字段越多,需要创建的索引就越少,从而最大限度地提高查询性能。