关于架构设计的建议 - MongoDB 或潜在的 Neo4J
Advice on schema design - MongoDB or potentially Neo4J
我正在构建一个供个人使用的简单会计程序 (MEAN stack)。我找到了 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]
});
虽然在我看来这是一种合理的数据存储方式,但存在一些明显的查询问题。例如,当我想查看一个帐户的分类帐时,我将不得不迭代该期间的所有交易,并为每个交易迭代信用和借记收款以检查是否涉及该帐户。
我对图形数据库没有任何经验,但我认为 Neo4J 之类的东西可能更适合查询此类数据。我的问题是,您是否同意 Mongo 仍然是一个不错的选择,但我在考虑模式错误?
是的,你是对的。在处理连接数据时,Neo4j 是一个不错的选择。
您当前的策略基本上是嵌入对来自其他模式的标识符的引用(一种外键)。在查询时,它将需要全扫描和类似连接的操作,随着数据库大小的增加变得非常昂贵。
此外,您需要注意这些引用数据的更新和删除。否则,您将得到不一致的数据。
我认为,使用像 Neo4j 这样的图形数据库,您的数据模型将是一个图形,这对您的场景来说更 "natural" 和直观。我不完全理解您的要求和场景,但我相信图形数据模型可以是这样的:
这样您就可以使用 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. Also, you can download the e-books: Graph Databases (By Ian Robinson, Jim Webber, and Emil Eifrém) and Learning Neo4j(作者 Rik Van Bruggen)。
我正在构建一个供个人使用的简单会计程序 (MEAN stack)。我找到了 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]
});
虽然在我看来这是一种合理的数据存储方式,但存在一些明显的查询问题。例如,当我想查看一个帐户的分类帐时,我将不得不迭代该期间的所有交易,并为每个交易迭代信用和借记收款以检查是否涉及该帐户。
我对图形数据库没有任何经验,但我认为 Neo4J 之类的东西可能更适合查询此类数据。我的问题是,您是否同意 Mongo 仍然是一个不错的选择,但我在考虑模式错误?
是的,你是对的。在处理连接数据时,Neo4j 是一个不错的选择。
您当前的策略基本上是嵌入对来自其他模式的标识符的引用(一种外键)。在查询时,它将需要全扫描和类似连接的操作,随着数据库大小的增加变得非常昂贵。
此外,您需要注意这些引用数据的更新和删除。否则,您将得到不一致的数据。
我认为,使用像 Neo4j 这样的图形数据库,您的数据模型将是一个图形,这对您的场景来说更 "natural" 和直观。我不完全理解您的要求和场景,但我相信图形数据模型可以是这样的:
这样您就可以使用 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. Also, you can download the e-books: Graph Databases (By Ian Robinson, Jim Webber, and Emil Eifrém) and Learning Neo4j(作者 Rik Van Bruggen)。