向文件转储和恢复树数据结构

Posted

技术标签:

【中文标题】向文件转储和恢复树数据结构【英文标题】:Dump and restore a tree data structure to/from a file 【发布时间】:2013-10-21 19:00:27 【问题描述】:

我有一个带有一组特定类的 n 叉树数据结构。数据结构经过一组转换,例如 1 到 n。在上述转换结束时,最终的树是用于检索信息的输出结果。

有没有一种方法可以在每次正确转换后(二进制)转储树。转储将反映上一次转换后树的状态。因此,如果任何转换出错,我可以恢复内存中的转储,而无需再次进行正确的转换。它类似于 GDB 提供的检查点功能,用于保存程序状态的快照。

我查看了 NoSQL 数据库,如 MongoDB、CouchDB、Redis 等,但它们主要是键值数据存储 (Redis) 或将信息存储在文档类型结构中,不存储树中节点之间的关联/关系( MongoDB)。 我还查看了 Neo4j 图形数据库,它是表示图形结构的绝佳工具。

Redis-dump、Neo4j-dump 和 MongoDB-dump 可用,但我无法决定在其中选择哪一个。由于转储创建和恢复时间不应该很长,因此上述哪个更容易填充。

我想知道遇到这个问题的程序员的意见和反馈 以及他们是如何解决的。这样做的最佳方法是什么?

附:我现有的实现是用 C++ 编写的。如果有任何不清楚的地方请告诉我,我会尝试以更好的方式解释。

【问题讨论】:

【参考方案1】:

您需要做的是为树中的每个节点添加一个serialize 方法。此方法需要知道如何序列化自身及其所有子级。

序列化节点本身特定于节点中存储的数据,尽管您可能会使用某种形式的类型-长度-值格式。序列化孩子是递归完成的。

唯一棘手的事情是找出您需要创建多大的缓冲区。为此,您可能需要一个递归方法来计算缓冲区大小。

如果您将数据保存在一个漂亮的平面缓冲区中,您可以将其保存到平面文件中,或者如果更简单,可以保存到某种数据库中。

【讨论】:

有一个开源项目可以帮助序列化code.google.com/p/protobuf。它具有一些不错的功能,例如向前和向后兼容性。可能还有其他人。 总有ASN.1 感谢 doron 和 @Sorin 的回答和反馈。将看看序列化方法。【参考方案2】:

在 Neo4j 中,您是否可以简单地维护数据库中的每一代模式,直到您对结果感到满意,然后删除多余的代?您可以创建一个节点,例如

(t1:Transformation transformationId:1)

充当一组转换的索引或锚点,然后创建每一代新模式并将其与具有排序属性的关系的转换节点相关联

(t1)-[:STEP order:0]->(root)-[:..*]->(branch) //tree
(t1)-[:STEP order:1]->(transformedRoot)-[:..*]->(transformedBranch) //first transformed tree
(t1)-[:STEP order:2]->(transformedRoot2)-[:..*]->(transformedBranch2) //second transformed tree

在转换中未更改的节点可以直接包含在新模式中

(t1)-[:STEP order:3]->(transformedRoot)-[:..*]->(originalBranch) // transformed tree with original branch

直到它们确实被改变

(t1)-[:STEP order:4]->(transformedRoot)-[:..*]->(transformedBranch)

只要您愿意,您就可以获得每个转换的快照,并且您可以与它交互以在数据库中回滚、比较或做任何您想做的事情,而不是导出/导入转储。

编辑: 回复您的评论1) Neo4j 会扩展或替换您的 C++ 实现吗?如果替换,有several tools用于将初始数量的数据导入Neo4j,特别注意1和2。

如果扩展,则取决于您将如何与数据交互。据我所知,C++ 没有非常好的 Neo4j 驱动程序,尽管有一些或多或少成熟的项目(1、2、3 和3,还有4)可能会有所帮助.我会 run Neo4j as a server 并构建一个 RESTful 客户端 (1,2,3),它使用 Cypher & (de)serialized JSON 与之通信。我会花时间学习制作good cypher queries,并使用transactional server endpoint。但是,我会用 Java 或 Python 或其他具有良好 driver support for Neo4j 的语言来执行此操作,可能不是 C++。

2) 没有数据很难举出例子。首先查看modeling examples,然后在Google Group discussions 中搜索线程,人们会在其中详细了解他们如何为他们的域建模和设计他们的查询。例如Here 和here 是指两种不同的关系排序方式;按关系属性和关系类型。然后,如果您需要建模或查询方面的帮助,请将示例数据放入 Neo4j Console 并与您在 SO 上的问题一起分享链接。 (我在链接的控制台中放了一个带有查询的小样本,你可以开始玩了。)

【讨论】:

谢谢。好主意啊。由于我是 Neo4j 的新手,您能否分享 1. 从我的 C++ 实现中填充 Neo4j 数据库的最佳策略是什么,以及 2. 有关转换节点排序的更多信息。一个链接/教程会很好。 感谢您的编辑...感谢我提供了很多信息,非常感谢您的努力。 :) 我将赏金奖励给你,因为我的内心感觉正在推动我尝试使用 Neo4j。也会尝试序列化方法。【参考方案3】:

我相信您想要的是 boost::serialize 提供的功能。它将为您序列化和反序列化 STL 集合。

请看这里: http://www.boost.org/doc/libs/1_54_0/libs/serialization/doc/tutorial.html#stl

【讨论】:

感谢您的回答。将看看序列化方法。

以上是关于向文件转储和恢复树数据结构的主要内容,如果未能解决你的问题,请参考以下文章

数据库原理-数据恢复

我可以使用帮助二进制转储文件恢复数据库 clickhouse 吗?

如何从 mysqldump 恢复转储文件?

如何使用 kubernetes 从 mysqldump 恢复转储文件?

sh 转储和恢复mongo数据

如何使用现有模型和迁移恢复 Django 项目的转储数据库备份?