关于模式设计的建议 - MongoDB或潜在的Neo4J

时间:2017-10-17 18:15:10

标签: mongodb neo4j database-schema

我正在构建一个供个人使用的简单会计程序(MEAN堆栈)。我接触了Mongo,因为我熟悉它,但是当我充实了我对疑惑的模式时。我想提出我的想法,并就可能的另一种方式提出建议。

由于同一事务必须在任意数量的帐户的分类帐上显示,我当前的想法是不将事务存储为帐户的子文档,而是将它们存储为自己的集合(以避免重复它们)。抛弃不重要的位,它看起来像这样:

var accountSchema = new mongoose.Schema({
    name: String,
    // etc
});

var entrySchema = new mongoose.Schema({
    amount: Number,
    account: {type: mongoose.Schema.Types.ObjectId, ref: 'Account'}
});

var transactionSchema = new mongoose.Schema({
    date: Date,
    debits: [entrySchema],
    credits: [entrySchema]
});

虽然在我看来这是存储数据的合理方式,但有一些明显的查询问题。例如,当我想要查看帐户的分类帐时,我将不得不迭代该期间的所有交易,并且每个交易都会迭代贷方和借方收款以检查是否涉及该帐户。

我没有图dbs的经验,但我认为像Neo4J这样的东西可能更适合查询这类数据。我的问题是,你是否同意或者Mongo仍然是一个不错的选择,但我认为这些模式错了?

1 个答案:

答案 0 :(得分:1)

是的,你是对的。在处理连接数据时,Neo4j是一个不错的选择。

您当前的策略基本上是嵌入对其他模式(一种外键)的标识符的引用。在查询时,它将需要完全扫描类似连接的操作,随着数据库大小的增加而变得非常昂贵。

此外,您需要关注这些引用数据的更新和删除。否则,您将获得不一致的数据。

对于像Neo4j这样的图形数据库,您的数据模型将是一个图形,我认为这对您的场景更“自然”和直观。我不完全理解你的要求和场景,但我相信图形数据模型可能是这样的:

Sample graph model

这样您就可以使用Cypher Language的强大功能来查询图表。例如,要获得“2017-10-10”以来给定帐户的所有积分,您可以执行以下操作:

MATCH(a:Account)<-[:ENTRY_TO]-(e:Entry)<-[:CREDIT]-(t:Transaction)
WHERE a.id = 10 AND t.date > "2017-10-10"
RETURN e

您可以利用无索引邻接来横向查询并以更低的成本查询图表,因为不需要连接操作。

由于您不熟悉Neo4j和图形数据库,我建议您查看免费的在线培训getting started with Neo4j。此外,您可以免费下载电子书:Graph Databases(由Ian Robinson,Jim Webber和EmilEifrém提供)和Learning Neo4j(由Rik Van Bruggen提供)。