電子商取引ビジネスの基本的な機能モジュールは、さまざまな製品の特性とパラメーターを格納することです。この記事では、MongoDB を使用して格納する方法を主に紹介します。製品分類情報。
リレーショナル データベース ソリューション
上記の問題は、次のソリューションなど、従来のリレーショナル データベースを使用して解決することもできます
製品ごとに異なるテーブルを作成します
たとえば、音楽アルバムと映画には、いくつかの共通の属性がありますですが、それらには多くの固有の属性もあります。異なるスキーマを使用して 2 つの異なるテーブルを作成できます。
CREATE TABLE `product_audio_album` ( `sku` char(8) NOT NULL, ... `artist` varchar(255) DEFAULT NULL, `genre_0` varchar(255) DEFAULT NULL, `genre_1` varchar(255) DEFAULT NULL, ..., PRIMARY KEY(`sku`)) ... CREATE TABLE `product_film` ( `sku` char(8) NOT NULL, ... `title` varchar(255) DEFAULT NULL, `rating` char(8) DEFAULT NULL, ..., PRIMARY KEY(`sku`)) ...
このアプローチの主な問題は、
新しい製品カテゴリごとに新しいテーブルを作成する必要があることです
アプリケーション開発者は、クエリのために対応するテーブルにリクエストを明示的に分散する必要があり、複数の製品をクエリする必要があります一度に実装するのは面倒です
すべての製品は単一のテーブルに保存されます
CREATE TABLE `product` ( `sku` char(8) NOT NULL, ... `artist` varchar(255) DEFAULT NULL, `genre_0` varchar(255) DEFAULT NULL, `genre_1` varchar(255) DEFAULT NULL, ... `title` varchar(255) DEFAULT NULL, `rating` char(8) DEFAULT NULL, ..., PRIMARY KEY(`sku`))
このテーブルには、すべての製品に必要な属性が含まれています。 , この方法では、製品クエリが簡素化され、1 つのクエリが複数の製品にまたがることができますが、多くのスペースを無駄にするという欠点があります。
パブリック属性の抽出、マルチテーブル継承
CREATE TABLE `product` ( `sku` char(8) NOT NULL, `title` varchar(255) DEFAULT NULL, `description` varchar(255) DEFAULT NULL, `price`, ... PRIMARY KEY(`sku`)) CREATE TABLE `product_audio_album` ( `sku` char(8) NOT NULL, ... `artist` varchar(255) DEFAULT NULL, `genre_0` varchar(255) DEFAULT NULL, `genre_1` varchar(255) DEFAULT NULL, ..., PRIMARY KEY(`sku`), FOREIGN KEY(`sku`) REFERENCES `product`(`sku`)) ... CREATE TABLE `product_film` ( `sku` char(8) NOT NULL, ... `title` varchar(255) DEFAULT NULL, `rating` char(8) DEFAULT NULL, ..., PRIMARY KEY(`sku`), FOREIGN KEY(`sku`) REFERENCES `product`(`sku`)) ...
上記のソリューションは、すべての製品の共通属性を抽出し、各製品に固有の情報のみを使用して新しいテーブルを作成します。この商品は保管されております。
エンティティ属性値はストレージを形成します
このソリューションは実際にリレーショナル データベースを KV ストレージとして使用しますが、複雑なデータを扱うのはあまり便利ではありません。クエリ。 Type omongodbソリューション
mognodb以来、タイプomognodbは、ドキュメントのコンテンツを非常に柔軟にカスタマイズできます文書の内容。たとえば、音楽アルバムは次のようなドキュメント構造を持つことができます
{ sku: "00e8da9b", type: "Audio Album", title: "A Love Supreme", description: "by John Coltrane", asin: "B0000A118M", shipping: { weight: 6, dimensions: { width: 10, height: 10, depth: 1 }, }, pricing: { list: 1200, retail: 1100, savings: 100, pct_savings: 8 }, details: { title: "A Love Supreme [Original Recording Reissued]", artist: "John Coltrane", genre: [ "Jazz", "General" ], ... tracks: [ "A Love Supreme Part I: Acknowledgement", "A Love Supreme Part II - Resolution", "A Love Supreme, Part III: Pursuance", "A Love Supreme, Part IV-Psalm" ], }, }
{ sku: "00e8da9d", type: "Film", ..., asin: "B000P0J0AQ", shipping: { ... }, pricing: { ... }, details: { title: "The Matrix", director: [ "Andy Wachowski", "Larry Wachowski" ], writer: [ "Andy Wachowski", "Larry Wachowski" ], ..., aspect_ratio: "1.66:1" }, }
所有商品都拥有一些共同的基本信息,特定的商品可以根据需要扩展独有的内容,非常方便; 基于上述模型,MongoDB 也能很好的服务各类查询。
查询某个演员参演的所有电影,并按发型日志排序
db.products.find({'type': 'Film', 'details.actor': 'Keanu Reeves'}).sort({'details.issue_date', -1})
上述查询也可以通过建立索引来加速
db.products.createIndex({ type: 1, 'details.actor': 1, 'details.issue_date': -1 })
查询标题里包含特定信息的所有电影
db.products.find({ 'type': 'Film', 'title': {'$regex': '.*hacker.*', '$options':'i'}}).sort({'details.issue_date', -1})
可建立如下索引来加速查询
db.products.createIndex({ type: 1, details.issue_date: -1, title: 1 })
扩展
当单个节点无法满足海量商品信息存储的需求时,就需要使用MongoDB sharding来扩展,假定大量的查询都是都会基于商品类型,那么就可以使用商品类型字段来进行分片。
db.shardCollection('products', { key: {type: 1} })
分片时,尽量使用复合的索引字段,这样能满足更多的查询需求,比如基于商品类型之后,还会经常根据商品的风格标签来查询,则可以把商品的标签字段作为第二分片key。
db.shardCollection('products', { key: {type: 1, 'details.genre': 1} })
如果某种类型的商品,拥有相同标签的特别多,则会出现jumbo chunk的问题,导致无法迁移,可以进一步的优化分片key,以避免这种情况。
db.shardCollection('products', { key: {type: 1, 'details.genre': 1, sku: 1} })
加入第3分片key之后,即使类型、风格标签都相同,但其sku信息肯定不同,就肯定不会出现超大的chunk。