【问题标题】:How to convert this RDBMS schema to a MongoDB "schema" (and how to query against it)如何将此 RDBMS 模式转换为 MongoDB“模式”(以及如何查询它)
【发布时间】:2012-06-19 19:25:08
【问题描述】:

我正在学习如何使用 MongoDB。我需要一段时间才能将我的思维方式从 RDBMS/SQL 转变为 NoSQL。

以下面的表格和查询为例,我希望有人能解释我如何使用 mongrel 实现这个简单的 RDBMS 架构,以及如何使用 mongodb 实现查询。

CREATE TABLE tag_category (id INT NOT NULL, name VARCHAR(32) );
CREATE UNIQUE INDEX idxu_tag_cat ON tag_category(name);

INSERT INTO tag_category(1, 'books');
INSERT INTO tag_category(3, 'music');
INSERT INTO tag_category(4, 'food');


CREATE TABLE tag (id INT NOT NULL, 
                  categ_id INT REFERENCES tag_category(id),
                  tagval   VARCHAR(32) NOT NULL
                 );

INSERT INTO tag (1,1,'romance');
INSERT INTO tag (2,1,'scifi');
INSERT INTO tag (3,1,'thriller');
INSERT INTO tag (4,2,'rap');
INSERT INTO tag (5,2,'country');
INSERT INTO tag (6,2,'jazz');
INSERT INTO tag (7,2,'classical');
INSERT INTO tag (8,3,'Chinese');
INSERT INTO tag (9,3,'Italian');
INSERT INTO tag (10,3,'French');
INSERT INTO tag (11,3,'South African');


CREATE TABLE item (id INT,
                  entry_date DATE NOT NULL, 
                  name VARCHAR(32) );
CREATE UNIQUE INDEX idxu_item ON item(name);

INSERT INTO item (id, entry_date, name) VALUES(1, '2011-01-01', 'A love supreme');
INSERT INTO item (id, entry_date, name) VALUES(2, '2011-01-01', 'A kind of blue');
INSERT INTO item (id, entry_date, name) VALUES(3, '2011-02-01', 'Believe the hype');
INSERT INTO item (id, entry_date, name) VALUES(4, '2011-01-01', 'Raising Hell');
INSERT INTO item (id, entry_date, name) VALUES(5, '2011-01-01', 'The Chronic');
INSERT INTO item (id, entry_date, name) VALUES(6, '2011-02-01', 'Blue Danube');
INSERT INTO item (id, entry_date, name) VALUES(7, '2011-01-01', 'Schubert Sonata in B flat');
INSERT INTO item (id, entry_date, name) VALUES(8, '2011-01-01', 'Also Sprach Zarathrustra' );
-- ...

CREATE TABLE item_tag (id INT, 
                       item_id INT REFERENCES tag(id),
                       name VARCHAR(32) );

-- INSERT INTO item_tag (id, item_id, name) VALUES () ....

查询

为简洁起见,我将描述一个查询,它(希望)包含我期望遇到的大多数用例场景。下面的查询使用 SQL 实现起来很简单 - 使用 mongrel,我不太确定该怎么做:

  • 获取所有标记为 RAP 或古典(在音乐类别中)且条目日期早于“2011-01-01”的项目

回顾一下我的问题:

  1. 我将如何“移植”上面的架构,以便在 mongodb 中实现它
  2. 如何使用 mongodb API 请求上述查询中描述的项目?

我熟悉 Python 和 PHP - 所以使用 PHP 或 Python API 的解决方案会很棒(尽管我偏向于 Python)。

【问题讨论】:

  • 你知道如何在 Python 中处理这个数据结构吗?
  • @AsyaKamsky:我不确定我是否理解你的问题。你能详细说明一下吗?。
  • 有时,如果您已经知道如何用您选择的语言表示数据,它自然会建议在文档数据库中以特定方式对其进行建模。因此,如果在 Python 中每个项目都是一个字典,而标签是 item['tags'] 的列表值,那么它会直接映射到 JSON 文档中。

标签: php python mongodb database-design nosql


【解决方案1】:

文档模式的好处是您不必从关系转换为它 - 您可以自己考虑它。考虑您将对集合进行的查询,然后考虑如何使用您选择的语言处理数据。

我会考虑类似于单个集合的东西,其中每个文档代表一个项目。每个项目都可以有一个名称、ID、进入日期,可能还有一个类别以及一组标签。我也可以考虑将类别放入标签数组中,就像它是另一个标签一样。这取决于查询以及我将存储的项目有多么不同(食物和音乐可能需要单独的类别字段)。

如果您将类别保留在其自己的字段中,您的文档可能如下所示:

{
    "_id" : 1,
    "entry_date" : ISODate("2011-01-01T05:00:00Z"),
    "title" : "A love supreme",
    "category" : "music",
    "tags" : [
        "jazz",
        "American"
    ]
}

如果你把它用作标签,它会是这样的:

{
    "_id" : 1,
    "entry_date" : ISODate("2011-01-01T05:00:00Z"),
    "title" : "A love supreme",
    "tags" : [
        "music",
        "American",
        "jazz"
    ]
}

现在要查询,您只需执行find 结合您想要的条件。如果是这样的话:

db.items.find({entry_date:{$gt:new Date(2011,0,1)},
                tags:{$in:["rap","classical"]}})

从技术上讲,如果您在电影或其他东西上可能有这些标签,您可以添加 category:"music"

第二种情况可能是:

db.items.find({entry_date:{$gt:new Date(2011,0,1)}, 
               tags:"music",tags:{$in:["rap","classical"]}})

由于您可以在 tags 数组上使用 multi-key indexes 并且 MongoDB 支持 compound indexes(如果您经常按标签和 entry_date 查询),这将是一个非常有效的查询。

【讨论】:

  • Asya:你能推荐一个链接(或书),其中包含构建简单应用程序(例如博客)的基本教程,使用 mongodb 作为后端(PHP 或 Python 都可以)。
猜你喜欢
  • 2011-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多