【问题标题】:Sending updates to objects from client to nodejs将对象的更新从客户端发送到 nodejs
【发布时间】:2018-03-02 08:52:50
【问题描述】:

目前我有一个 Angular2 应用程序,其中包含一个包含嵌套对象的对象。用户按照向导更新对象的任何部分,然后单击保存。目前,我只是将整个对象发送到服务器端进行更新。要进行更新,我从数据库中获取数据库副本,并将客户端副本具有的所有字段设置到数据库副本上,无论它们是否已更改,然后保存。这意味着我还必须遍历所有嵌套对象并将它们从数据库中拉出并设置它们的所有属性等等。一切都会更新,即使它没有改变。

这是我通常这样做的方式,但对于这个应用程序,我需要保留已更改对象的审核日志。如果每次更新主对象时,所有其他子对象都记录它的更新,这将是很困难的。

是否有一种优雅的方法来确保服务器端只知道更新已更改的内容(因此只触发该对象的审核日志并且不会浪费时间在数据库上进行更新)。

我正在考虑创建一个对象,该对象在用户更改向导中的内容时在客户端存储脏对象列表,并将其与对象一起发送到服务器,以便我知道哪些对象需要更新。

或者我应该像现在一样将整个对象发送到服务器,然后首先将其与原始数据库对象进行比较(通过遍历所有对象并比较它们)以确定发生了什么变化?

看起来工作量很大。我想知道是否有这样做的标准方法/最佳实践。

编辑 2018-04-24:我刚刚发现了 BreezeJS。这是我想要用来实现我的目标的东西吗?它跟踪实体及其修改状态,并在需要时将它们作为更改集进行相应更新。还有其他类似的东西我应该研究吗?

【问题讨论】:

  • 这都是 JSON 可表示的数据吗?
  • 是的。都是 JSON 数据。
  • 对我发布的解决方案有任何反馈吗?

标签: node.js design-patterns angular-cli


【解决方案1】:

你可以使用包deep-diff

var diff = require('deep-diff').diff;

var lhs = {
  name: 'my object',
  description: 'it\'s an object!',
  details: {
    it: 'has',
    an: 'array',
    with: ['a', 'few', 'elements']
  }
};

var rhs = {
  name: 'updated object',
  description: 'it\'s an object!',
  details: {
    it: 'has',
    an: 'array',
    with: ['a', 'few', 'more', 'elements', { than: 'before' }]
  }
};

var differences = diff(lhs, rhs);

下面是differences对象结构

[ { kind: 'E',
    path: [ 'name' ],
    lhs: 'my object',
    rhs: 'updated object' },
  { kind: 'E',
    path: [ 'details', 'with', 2 ],
    lhs: 'elements',
    rhs: 'more' },
  { kind: 'A',
    path: [ 'details', 'with' ],
    index: 3,
    item: { kind: 'N', rhs: 'elements' } },
  { kind: 'A',
    path: [ 'details', 'with' ],
    index: 4,
    item: { kind: 'N', rhs: { than: 'before' } } } ]

区别

差异报告为一个或多个更改记录。变更记录的结构如下:

kind - indicates the kind of change; will be one of the following:
   N - indicates a newly added property/element
   D - indicates a property/element was deleted
   E - indicates a property/element was edited
   A - indicates a change occurred within an array
path - the property path (from the left-hand-side root)
lhs - the value on the left-hand-side of the comparison (undefined if kind === 'N')
rhs - the value on the right-hand-side of the comparison (undefined if kind === 'D')
index - when kind === 'A', indicates the array index where the change occurred
item - when kind === 'A', contains a nested change record indicating the change that occurred at the array index

【讨论】:

  • 这可行。但我试图避免很多工作。得到差异后,我仍然需要查看它们并决定运行哪些 DB 语句。
【解决方案2】:

好的,这个怎么样..

  1. 与其在代码级别处理这个问题,不如像现在这样发送完整的对象。

  2. 在数据库中,您可以在有问题的表上设置一个触发器,以便在更新发生之前触发它。这样,您就可以将数据与来自外部世界的新数据一起更新。

  3. 在那里处理关于审核什么、拒绝什么等的决定。如果您发现某些内容正在更新,您甚至可以拒绝整个更新,这是不应该被允许的。

我的 2 美分..

【讨论】:

    【解决方案3】:

    在 github 上使用像 Tomato 这样的实体库。

    它是一个 java 库,其工作方式与基于普通实体的持久性机制的工作方式类似,但除了提供的单个实体之外,您不需要任何实体。提供的单个实体类可以从任何数据库的任何模式中的任何表或表层次结构中加载和保存数据。在代码中它看起来像这样......

    Entity e = Entity.createEntityOrView(schema.tablename);
    e.setValue("id", 5);
    e.load();
    

    或加载记录集...

    e.setFilter("name = 'rodney');
    e.load();
    

    实体类自动知道值何时变脏,因此将整个实体标记为脏。它还知道一个实体是从表中加载的还是新的(换句话说,您总是调用 save(),但它会知道是执行 INSERT 还是 UPDATE)。

    由于所有更改都通过 Entity 类中称为 save() 的单个方法保存,因此可以在自定义 Entity 类中轻松覆盖此方法,从而允许您修改 save() 之前和之后发生的情况。在您的自定义实体类中,您将能够输出详细的审计数据,包括表格、主键以及更改的确切值。

    Tomato 可用于在任何使用 JSON 的情况下立即满足数据库需求,例如通过单一提供的 Web 服务使用 Angular 或 vue(以及任何非 Java 代码)。

    查看 github 上的 Tomato 库!

    我是github上Tomato库的作者。

    【讨论】:

      猜你喜欢
      • 2018-02-13
      • 1970-01-01
      • 2013-11-16
      • 2020-08-17
      • 1970-01-01
      • 2015-10-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多