我有一个要求,产品需要实现撤消重做功能。
目前我持有一个来自单个 mongo 集合的巨大对象。
伪结构:
{
cart:{
products:[
{
name: "Watch",
quantity: 1,
shippingDate: 123456782,
text: "lorem ipsum....",
prices:[
{
currency: "USD",
price: 300
},
{
currency: "GBP",
price: 220
}
]
}
],
...someMoreKeyValuePair
}
}
现在更新可以在任何 Node 上进行,例如:添加/修改/删除产品,添加/修改/删除购物车级别数据。
结构很大,现在我如何维护整个结构上发生的任何更改的撤消重做操作。
我应该阅读哪些数据结构或设计模式才能获得更好的方法来解决这个问题。
更新:
undo-redo需要持久化在数据库中。我使用的语言是 Javascript-NodeJS
最佳答案
您需要保留更改日志。因此,服务器应用程序 (nodejs) 处理的客户端请求应转换为数据库操作,两者 记录更改(像撤消日志一样)并在一个事务中执行它。
然后实现逻辑以在适当的时候清除撤消日志,从该日志中弹出一个操作并执行相反的操作,...等等。
此类撤消日志中的记录将包含 3 到 4 个元素:
- 操作:“更新”、“插入”或“删除”。后两者主要用于表示数组操作。
- 用于标识应在对象中应用更改的位置的路径。该路径将是一个属性数组,例如可以将其编码为点分隔的字符串。
- 该位置的旧值(在“更新”或“删除”的情况下),JSON 编码。
- 该位置的新值(在“更新”或“插入”的情况下),JSON 编码。
此类记录的示例:
("更新", "cart.products.0.name", '"观看"', '"观看"')
("delete", "cart.products.prices.1", '{"currency":"GBP","price":220}', null)
:这代表一个操作其中旧值从prices
数组的索引 1 中删除。该间隙通过移位数组值来填补,就像 JavaScript 中的splice(index, 1)
操作一样。("insert", "cart.products.prices.0", null, '{"currency":"EUR","price":270}')
:这代表一个操作其中新值插入到prices
数组中的索引 0 处。如果该索引已经有一个值,则会向右移动,就像 JavaScript 中的splice(index, 0, newvalue)
操作一样。
null
值仅表示此参数与该特定操作无关。
上面的示例日志将从您给出的示例数据开始累积到以下数据:
{
cart:{
products:[
{
name: "Watching",
quantity: 1,
shippingDate: 123456782,
text: "lorem ipsum....",
prices:[
{
currency: "EUR",
price: 270
},
{
currency: "USD",
price: 300
}
]
}
]
}
}
这样的日志具有撤消操作的一切:如果数据被删除(“更新”、“删除”),您可以从第三个参数恢复被删除的数据。
关于javascript - 对巨大对象进行撤消重做,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58324932/