代表couchDB中的多对多关系

时间:2009-11-30 21:15:26

标签: couchdb nosql non-relational-database

假设我正在编写日志分析应用程序。主域对象是LogEntry。此外。应用程序的用户定义了一个LogTopic,它描述了他们感兴趣的日志条目。当应用程序接收日志条目时,它会将它们添加到couchDB,并根据系统中的所有LogTopics检查它们,看它们是否与主题中的条件匹配。如果是,则系统应记录该条目与主题匹配。因此,LogEntries和LogTopics之间存在多对多关系。

如果我将它存储在RDBMS中,我会做类似的事情:

CREATE TABLE Entry (
 id int,
 ...
)

CREATE TABLE Topic (
 id int,
 ...
)

CREATE TABLE TopicEntryMap (
 entry_id int,
 topic_id int
)

使用CouchDB我首先尝试只有两种文档类型。我有一个LogEntry类型,看起来像这样:

{
  'type': 'LogEntry',
  'severity': 'DEBUG',
  ...
}

我有一个LogTopic类型,看起来像这样:

{
  'type': 'LogTopic',
  'matching_entries': ['log_entry_1','log_entry_12','log_entry_34',....],
  ...
}

通过在每个LogTopic文档中使用matching_entries字段来存储LogEntry文档ID列表,您可以看到我表示关系。这在某种程度上可以正常工作,但是当多个客户端都试图向主题添加匹配条目时,我遇到了问题。两者都尝试乐观更新,一个失败。我现在使用的解决方案是基本上重现RDBMS方法,并添加第三种文档类型,如:

{
  'type':'LogTopicToLogEntryMap',
  'topic_id':'topic_12',
  'entry_id':'entry_15'
}

这可行,并且已经过了并发更新问题,但我有两个保留:

  1. 我担心我只是在使用它 因为这就是我要做的事情 关系数据库。我想知道是否有 更像couchDB(放松吗?) 解。
  2. 我的观点已不复存在 检索a的所有条目 一个电话中的特定主题。我的 以前的解决方案允许(如果我 使用了include_docs参数)。
  3. 任何人都有更好的解决方案吗?如果我也发布了我正在使用的观点会有帮助吗?

3 个答案:

答案 0 :(得分:11)

我通过Christopher Lenz将此问题交叉发布到couchdb users mailing list和Nathan Stott pointed me tovery helpful blog post

答案 1 :(得分:4)

你的方法很好。使用CouchDB并不意味着你只会放弃关系建模。您需要运行两个查询,但这是因为这是一个“连接”。带有连接的SQL查询也很慢,但SQL语法允许您在一个语句中表达查询。

在我使用CouchDB的几个月中,这是我发现的:

  1. 没有架构,因此设计应用程序模型既快速又灵活
  2. CRUD就在那里,因此开发您的应用程序既快速又灵活
  3. 再见SQL注入
  4. 什么是SQL连接需要在CouchDB中进行更多的工作
  5. 根据您的需要,我发现couchdb-lucene对于构建更复杂的查询也很有用。

答案 2 :(得分:0)

我尝试设置关系,以便LogEntrys知道它们属于哪个LogTopics。这样,插入LogEntry不会产生冲突,因为不需要更改LogTopics。

然后,一个简单的map函数会为它所属的每个LogTopic发出一次LogEntry,实际上是动态构建你的TopicEntryMap:

"map": function (doc) {
    doc.topics.map(function (topic) {
        emit(topic, doc);
    });
}

这样,使用?key=<topic>参数查询视图将为您提供属于某个主题的所有条目。