0

我正在开发一个将为用户发布定期 XML 更新的项目。我试图压制自上次更新以来没有改变的信息。

在 node.js 中,我组装了一个用于生成 XML 的用户对象:

users = 
  # actual application has 25 properties per user
  [
    {
      USERID: 150927,
      EMAIL: 'irving.block@email.net',
      FIRSTNAME: 'Irving',
      LASTNAME: 'Block',
      COLOR: 'Green'
    },
    {
      USERID: 1246007,
      EMAIL: 'allen.adler@email.net',
      FIRSTNAME: 'Adler',
      LASTNAME: 'Allen',
      COLOR: 'Blue'
    },
    {
      CLKEY: 1248350,
      EMAIL: 'walter.pidgeon@email.net',
      FIRSTNAME: 'Walter',
      LASTNAME: 'Pidgeon',
      COLOR: 'Red'
    }
  ]

我还加载了一个对象,它有助于将用户数据映射到最终的 XML 字段:

xml_map =
  [
    {
      ID: 1,
      ELEMENT: 'xml_map_assigned_id',
      MAPPPED: 'USERID' 
    },
    {
      ID: 2,
      ELEMENT: 'xml_map_email_address',
      MAPPPED: 'EMAIL' 
    },
    {
      ID: 3,
      ELEMENT: 'xml_map_user_firstname',
      MAPPPED: 'FIRSTNAME' 
    },
    {
      ID: 4,
      ELEMENT: 'xml_map_user_lastname',
      MAPPPED: 'LASTNAME' 
    },
    {
      ID: 5,
      ELEMENT: 'xml_map_user_color',
      MAPPED: 'COLOR'
    }
  ]

使用这些对象,我需要与上次更新进行比较,并删除匹配的属性(因为我只想发布已更改数据的更新)。这是最后一次更新(存储在数据库中)的示例:

# nothing like this is used in the real application
# just showing here to give an idea of what the DB could look like
db_data = 
  [ 
    {
      USERID: 150927,
      EMAIL: 'irving.block@email.net',
      FIRSTNAME: 'IRVING',
      LASTNAME: 'Block',
      COLOR: 'Orange'
    },
    {
      USERID: 1246007,
      EMAIL: 'new.email@somewhere.com',
      FIRSTNAME: 'Adler',
      LASTNAME: 'Allen',
      COLOR: 'Blue'
    },
    {
      USERID: 1248350,
      EMAIL: 'walter.pidgeon@email.net',
      FIRSTNAME: 'Walt',
      LASTNAME: 'Pidgeon',
      COLOR: 'Red'
    }
  ]

使用这些示例,我想最终得到一个这样的 User 对象(因为每个用户只有一件事发生了变化):

users_final = 
  [
    {
      USERID: 150927,
      COLOR: 'Orange'
    },
    {
      USERID: 1246007,
      EMAIL: 'new.email@somewhere.com',
    },
    {
      USERID: 1248350,
      FIRSTNAME: 'Walt',
    }
  ]

现在对于显示我一直在尝试完成此操作的伪代码:

async = require "async"

handleChanges = (users, map, callback) ->
  sql1 = "select..."
  sql2 = "update..."
  sql3 = "insert..."
  db.query sql1, [], (err, rows, def) ->
    if err? then console.log err
    if rows[0]
      if rows[0].ELEMENT_VALUE.toString() is users[map.MAPPED].toString() 
      # nothing has changed since last update
        db.query sql2, ['Old'], (err, rows, def) ->
          if err? then console.log err
          callback null, map.MAPPED
      else # this value has changed since the last update. Run update query
        db.query sql2, ['New'], (err, rows, def) ->
          if err? then console.log err
          callback null, null
    else # no value has ever been saved for this combo. Run insert query
      db.query sql3, [], (err, rows, def) ->
        if err? then console.log err
        callback null, null

updateStore = (users, callback) ->
  for map in xml_map
    do(map) ->
      handleChanges users, map, (err, del) ->
        if del? then delete r[del]
  callback null, r

async.map users, updateStore, (err, results) ->
  console.log results

这显然是行不通的。我确定 updateStore 函数需要做一些不同的事情,但我不知所措。

在此先感谢您的帮助!

4

2 回答 2

1

我在项目中做了类似的事情,但我使用 json 而不是 xml。

我所做的是从数据库中检索对象列表。并计算每个对象的哈希值。

users = 
  [
    {
      USERID: 150927,
      EMAIL: 'irving.block@email.net',
      FIRSTNAME: 'Irving',
      LASTNAME: 'Block',
      COLOR: 'Green'
    },
    {
      USERID: 1246007,
      EMAIL: 'allen.adler@email.net',
      FIRSTNAME: 'Adler',
      LASTNAME: 'Allen',
      COLOR: 'Blue'
    }
  ]
hash = [
  'c8addc875913a367486ba8343f68e349667e0334',
  'df3d067e876437996237d0fde90466703ea303b9'
]

在客户端,我将每个旧哈希与新哈希进行比较。如果不同,我使用 php.js 或 underscore.js。php.js 可以做 array_diff 来获得两个对象之间的差异。当然,您可以通过比较哈希来做 array_diff。

如果您的数据结构是这样嵌套的

{
  User: {
    FIRSTNAME: 'Irving',
    LASTNAME: 'Block',
    USERID: 150927
  }
  OtherInfo: {
    EMAIL: 'irving.block@email.net'
  }
}

您可以在执行 array_diff 之前将其展平为跟随,因为 array_diff 仅在一个级别上工作。

{
  "User.FIRSTNAME": 'Irving',
  "User.LASTNAME": 'Block',
  "User.USERID": 150927,
  "OtherInfo.EMAIL": 'irving.block@email.net'
}
于 2012-12-04T02:49:18.950 回答
0

我不确定是否有足够的关于您预期的 XML 输出的信息可供我帮助,但是users_final您正在寻找的结果可以使用相当直接的比较算法来计算。核心算法是:

difference = (a, b, idFieldName) ->
  if a[idFieldName] != b[idFieldName]
    throw new Error("#{idFieldName} values must match.")
  diff = {}
  diff[idFieldName] = a[idFieldName]
  isDifferent = false
  for key, value of b
    if key != idFieldName and a[key].toUpperCase() != value.toUpperCase()
      isDifferent = true
      diff[key] = value
  if isDifferent
    return diff
  else
    return false

是一个完整的示例,包括使用您提供的输入......但有一个例外。我认为您的users文字中有错字。我将它从 切换CLKEYUSERID以便它与其他行匹配。只需点击链接后右上角的“运行”按钮即可查看您的预期users_final结果。

于 2012-12-05T04:17:52.620 回答