2017-10-17 112 views
1

我正在构建一个简单的个人使用的会计程序(MEAN堆栈)。因为我熟悉Mongo,所以我到达了Mongo,但是当我充实了我怀疑的模式时。我想介绍我的想法,并可能以另一种方式征求建议。由于同一交易必须在任意数量的账户的账本上显示,我目前的想法是不将交易存储为账户的​​子文档,而是作为他们自己的收藏(以避免重复)。而忽略了重要比特,它会是这个样子:关于模式设计的建议 - MongoDB或潜在的Neo4J

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

是的,你是对的。处理连接的数据时,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(By Rik Van Bruggen)。

+1

我感谢您的详细回复;你证实了我的怀疑。这对我来说是学习新事物的好起点,这永远是一场胜利。 – amnesia