我正在构建一个供个人使用的简单会计程序(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仍然是一个不错的选择,但我认为这些模式错了?
答案 0 :(得分:1)
是的,你是对的。在处理连接数据时,Neo4j是一个不错的选择。
您当前的策略基本上是嵌入对其他模式(一种外键)的标识符的引用。在查询时,它将需要完全扫描类似连接的操作,随着数据库大小的增加而变得非常昂贵。
此外,您需要关注这些引用数据的更新和删除。否则,您将获得不一致的数据。
对于像Neo4j这样的图形数据库,您的数据模型将是一个图形,我认为这对您的场景更“自然”和直观。我不完全理解你的要求和场景,但我相信图形数据模型可能是这样的:
这样您就可以使用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提供)。