Coffeescript / Node.js - How to remove elements from an object based on comparison with DB

I'm working on a project which will post periodic XML updates for users. I'm attempting to suppress information which hasn't changed since the last update.

Within node.js, I have assembled a user object which will be used to generate the 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'
    }
  ]

I also have an object loaded which helps map user data to the eventual XML fields:

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'
    }
  ]

Using these objects, I need to compare with the last update, and remove matching properties (since I only want to post updates for data that has changed). Here's an example of what the last update (stored in the DB) might look like:

# 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'
    }
  ]

Using these examples, I'd like to end up with a User object like this (since only 1 thing has changed for each user):

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

And now for the pseudo-code that shows how I've been trying to accomplish this:

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

This obviously doesn't work right. I'm sure the updateStore function needs to be doing something different, but I'm at a loss.

Thanks in advance for your help!

I did similar thing in the project, but I use json instead of xml.

What I have done is retrieve a list of objects from db. and calculate a hash value for each of the object.

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'
]

on the client side, I do compare the each old hash to the new hash. if different I use php.js or underscore.js. php.js can do array_diff to get differents between two object. Of course you can just do array_diff with comparing hash.

If your data structure is nested like this

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

you can flatten it to following before doing array_diff because array_diff only work on one level.

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

I'm not sure if there is enough information about your expected XML output for me to help there, but the users_final result you are looking for can be calculated with a fairly straight forward comparison algorithm. The core algorithm is:

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

Here is a fully working example including using the input you provided... with one exception. I think you have a typo in your users literal. I switched it from CLKEY to USERID so it matches the other rows. Just click on the "Run" button in the upper right hand corner after following the link to see your expected users_final result.