面试题答案
一键面试数据建模方案
- 文档结构设计:
- 通用字段:在每个商品文档中,包含通用的字段,如
_id
(商品唯一标识)、basicDescription
(基本描述)、price
(价格)、stock
(库存)和comments
(评论数组,每个元素包含评论内容、评论者等信息)。例如:
{ "_id": "商品ID1", "basicDescription": "这是一款手机", "price": 3999, "stock": 100, "comments": [ { "content": "手机很好用", "commenter": "用户1" }, { "content": "拍照效果不错", "commenter": "用户2" } ], "category": "电子产品", "specificAttributes": { "brand": "某品牌", "model": "型号1", "screenSize": "6.5英寸" } }
- 特定属性:对于不同类别的商品,使用一个字段(如
specificAttributes
)来存储特定属性,该字段是一个对象,其键值对根据商品类别不同而不同。这样既保证了不同类别商品特定属性的灵活性,又能在一个文档中统一管理商品信息。
- 通用字段:在每个商品文档中,包含通用的字段,如
- 索引设计:
- 单字段索引:
- 为
category
字段创建单字段索引,以便快速根据商品类别筛选商品。在MongoDB中可以使用db.products.createIndex({category: 1})
创建升序索引,这样在查询某一类别商品时,MongoDB可以利用索引快速定位相关文档。 - 为
price
字段创建单字段索引,例如db.products.createIndex({price: 1})
。这样在根据价格范围筛选商品时,如db.products.find({price: {$gte: 100, $lte: 500}})
,MongoDB可以利用索引快速找到符合价格范围的商品。
- 为
- 复合索引:如果经常需要同时根据商品类别和价格范围筛选商品,可以创建复合索引
db.products.createIndex({category: 1, price: 1})
。复合索引中字段的顺序很重要,在查询时如果查询条件的顺序与复合索引字段顺序一致,索引的利用效率会更高。 - 计算字段索引:为了高效获取商品的评论总数,可以在文档中增加一个
commentCount
字段,每次有新评论时更新该字段的值。然后为commentCount
字段创建索引db.products.createIndex({commentCount: 1})
。这样在查询评论总数时,如db.products.find({commentCount: {$gt: 100}})
,可以利用索引快速找到评论数满足条件的商品。
- 单字段索引:
数据建模对查询性能的影响
- 文档结构影响:
- 优点:将通用字段和特定属性放在同一个文档中,减少了查询时的连接操作。在关系型数据库中,如果不同类别商品特定属性用不同表存储,查询时可能需要进行复杂的表连接,而MongoDB的这种文档结构设计避免了这种情况,提高了查询效率。例如,查询一款电子产品的所有信息,直接查询该商品文档即可,无需进行表连接操作。
- 缺点:如果特定属性非常多,可能会导致文档过大,影响存储和读取性能。而且如果某些特定属性很少使用,也会占用不必要的空间。
- 索引影响:
- 优点:单字段索引和复合索引的使用,极大地提高了根据商品类别和价格范围筛选商品的速度。MongoDB可以通过索引快速定位到符合条件的文档,避免了全表扫描。例如,有大量商品数据时,没有索引的情况下查询某一类别且价格在一定范围的商品,可能需要遍历整个集合;而有了索引,能够快速定位到相关文档。计算字段索引使得获取商品评论总数的查询更加高效,因为可以直接利用索引找到符合评论数条件的商品。
- 缺点:索引会占用额外的存储空间,并且每次文档更新时,相关索引也需要更新,这会增加写操作的开销。例如,每次商品价格更新时,
price
字段的索引也需要更新,所以在设计索引时需要权衡读操作和写操作的频率,避免过多索引影响写性能。