我有2个对象,1个来自SQL数据库,另一个来自JSON REST API。在使用来自api的新数据更新db中的行之前,我不仅要检查db中是否已经出现ID(这意味着更新而不是插入),还要检查大部分属性。这样做的原因是,当在数据库端进行更新时,会添加一个额外的“lastUpdate”日期时间,以便以后在PowerBI中进行处理,如果我只检查ID,那么每次都会触发“lastUpdate”来自API的条目已经在数据库中,即使其属性未实际更新。每一方的单个对象(它们以数组形式出现)如下:
案例和说明:
重要:此部分是根据Nina Scholz(现在)已接受的解决方案添加的。请在阅读时记住这一点。
如果路径在API端不可完全遍历(即它的父级为空),则它应返回Null。这方面的一个例子是数据库的侧面callerLocationID在API上的路径callerLocation.id
,但是当没有设置callerLocation时,父callerLocation
已经null
,因此{{1}无法访问
如果路径两侧都可以完全遍历,则需要比较这些值。
如果无法在API端遍历应该为id
的路径。例如,我可以将null
与callerLocationID: null
进行比较,因为后者为callerLocation.id
而null
与null
遍历所有路径并比较所有值后,我需要知道“是的,它们都是相同的”(null
)或“不是它们不相同”(true
) 。不需要知道其中它们不相同如果不相同,则发送整个对象进行更新。
数据库方面的路径基本上是一成不变的,如果其中任何一个是false
,那是因为它们在数据库中是允许的,并且可以接受
数据库端以null
结尾的所有属性(ID
除外)都是指API中的单个嵌套incidentID
值。例如id
引用callerID
,caller.id
引用callerBranchID
和callerBranch.id
引用operatorID
有些例外情况是:
operator.id
引用impact
impact.name
引用urgency
urgency.name
引用priority
priority.name
引用duration
duration.name
引用escalationOperator
可以忽略API中的所有escalationOperator.id
内容
optionalField
和
// Database Object
{
incidentID: '0dc1a10f-2899-485a-b814-f72f29c9a15a',
status: 'secondLine',
briefDescription: 'Support niet bereikbaar',
callDate: '2018-04-10T19:01:00.000Z',
lastUpdate: '2018-04-18T14:02:17.000Z',
number: 'M1804 021',
request: '10-04-2018 21:02 Middelkoop, Paul: \nIk kan de servicedesk niet bereiken, telkens in gesprek',
callerID: '4e723042-0037-4e05-a362-e65c620ba734',
callerBranchID: 'f66e7804-b57a-4418-a991-997e574ead29',
callerLocationID: null,
externalNumber: null,
categoryID: 'cafb0af8-e43a-4391-ac9e-a0345abbcc4f',
subcategoryID: 'f56099a9-7c60-45e3-94b4-6555a79d4bd7',
callTypeID: '04b678a6-791e-4662-9bc8-97573555f15e',
entryTypeID: 'a9c486fd-a93e-565e-bfeb-17619fafe1a8',
branchID: null,
locationID: null,
impact: null,
urgency: null,
priority: null,
duration: null,
operatorID: 'a17aba85-13a7-4ac6-8c57-693a512b633e',
operatorGroupID: 'a17aba85-13a7-4ac6-8c57-693a512b633e',
supplierID: null,
targetDate: '2019-04-10T15:30:00.000Z',
onHold: false,
onHoldDate: null,
onHoldDuration: 0,
feedbackMessage: null,
feedbackRating: null,
processingStatus: 'Afgemeld',
completed: true,
completedDate: '2018-04-10T19:09:00.000Z',
closed: true,
closedDate: null,
closureCode: null,
creatorID: '226082ea-8d74-4dee-ae1e-74c33c883792',
creationDate: '2018-04-10T19:02:34.000Z',
timeSpent: 0,
timeSpentFirstLine: 0,
timeSpentSecondLineAndPartials: 0,
costs: 0,
escalationStatus: null,
escalationReason: null,
escalationOperator: null,
modifier: '226082ea-8d74-4dee-ae1e-74c33c883792',
modificationDate: '2018-04-10T19:12:08.000Z',
expectedTimeSpent: 0,
majorCall: false,
majorCallID: null,
publishToSSD: false,
monitored: false,
archivingReason: null
}
到目前为止我已经做了什么
迭代API对象数组,并且对于每一个都检查ID是否是使用Fuse.JS的数据库对象数组(阈值为0,仅用于完美匹配)
使用来自1的结果和来自UnderscoreJS的.first,.keys和.pick方法的组合来确定当前迭代中2个对象之间的哪些键是相同的,目的是快速检查这些
// API Object
{
id: '0dc1a10f-2899-485a-b814-f72f29c9a15a',
status: 'secondLine',
number: 'M1804 021',
request: '10-04-2018 21:02 Middelkoop, Paul: \nIk kan de servicedesk niet bereiken, telkens in gesprek',
requests: '/tas/api/incidents/id/0dc1a10f-2899-485a-b814-f72f29c9a15a/requests',
action: '/tas/api/incidents/id/0dc1a10f-2899-485a-b814-f72f29c9a15a/actions',
attachments: '/tas/api/incidents/id/0dc1a10f-2899-485a-b814-f72f29c9a15a/attachments',
caller: {
id: '4e723042-0037-4e05-a362-e65c620ba734',
dynamicName: 'Mafficioli del Castelletto, Richard',
branch: {
id: 'f66e7804-b57a-4418-a991-997e574ead29',
name: 'Ask Roger! Delft',
clientReferenceNumber: '',
timeZone: 'Europe/Amsterdam',
extraA: null,
extraB: null
}
},
callerBranch: {
id: 'f66e7804-b57a-4418-a991-997e574ead29',
name: 'Ask Roger! Delft',
clientReferenceNumber: '',
timeZone: 'Europe/Amsterdam',
extraA: null,
extraB: null
},
callerLocation: null,
branchExtraFieldA: null,
branchExtraFieldB: null,
briefDescription: 'Support niet bereikbaar',
externalNumber: '',
category: {
id: 'cafb0af8-e43a-4391-ac9e-a0345abbcc4f',
name: 'Communicatie'
},
subcategory: {
id: 'f56099a9-7c60-45e3-94b4-6555a79d4bd7',
name: 'Vaste telefonie'
},
callType: {
id: '04b678a6-791e-4662-9bc8-97573555f15e',
name: 'Klacht'
},
entryType: {
id: 'a9c486fd-a93e-565e-bfeb-17619fafe1a8',
name: 'Mondeling'
},
object: null,
branch: null,
location: null,
impact: null,
urgency: null,
priority: null,
duration: null,
targetDate: '2019-04-10T15:30:00.000+0000',
onHold: false,
onHoldDate: null,
onHoldDuration: 0,
feedbackMessage: null,
feedbackRating: null,
operator: {
id: 'a17aba85-13a7-4ac6-8c57-693a512b633e',
status: 'operatorGroup',
name: 'Systeembeheer'
},
operatorGroup: {
id: 'a17aba85-13a7-4ac6-8c57-693a512b633e',
name: 'Systeembeheer'
},
supplier: null,
processingStatus: {
id: '70b2967d-e248-4ff9-a632-ec044410d5a6',
name: 'Afgemeld'
},
completed: true,
completedDate: '2018-04-10T19:09:00.000+0000',
closed: true,
closedDate: '2018-04-10T19:12:00.000+0000',
closureCode: null,
timeSpent: 0,
timeSpentFirstLine: 0,
timeSpentSecondLineAndPartials: 0,
costs: 0,
escalationStatus: null,
escalationReason: null,
escalationOperator: null,
callDate: '2018-04-10T19:01:00.000+0000',
creator: {
id: '226082ea-8d74-4dee-ae1e-74c33c883792',
name: 'Middelkoop, Paul'
},
creationDate: '2018-04-10T19:02:34.000+0000',
modifier: {
id: '226082ea-8d74-4dee-ae1e-74c33c883792',
name: 'Middelkoop, Paul'
},
modificationDate: '2018-04-10T19:12:08.000+0000',
majorCall: false,
majorCallObject: null,
publishToSsd: false,
monitored: false,
expectedTimeSpent: 0,
archivingReason: null,
optionalFields1: {
boolean1: false,
boolean2: false,
boolean3: false,
boolean4: false,
boolean5: false,
number1: 0,
number2: 0,
number3: 0,
number4: 0,
number5: 0,
date1: null,
date2: null,
date3: null,
date4: null,
date5: null,
text1: '',
text2: '',
text3: '',
text4: '',
text5: '',
memo1: null,
memo2: null,
memo3: null,
memo4: null,
memo5: null,
searchlist1: null,
searchlist2: null,
searchlist3: null,
searchlist4: null,
searchlist5: null
},
optionalFields2: {
boolean1: false,
boolean2: false,
boolean3: false,
boolean4: false,
boolean5: false,
number1: 0,
number2: 0,
number3: 0,
number4: 0,
number5: 0,
date1: null,
date2: null,
date3: null,
date4: null,
date5: null,
text1: '',
text2: '',
text3: '',
text4: '',
text5: '',
memo1: null,
memo2: null,
memo3: null,
memo4: null,
memo5: null,
searchlist1: null,
searchlist2: null,
searchlist3: null,
searchlist4: null,
searchlist5: null
}
}
相同的KeysTd将导致:
// tdIncidents is the array of objects from the API
// dbIncidents is the array of objects from the database
// tdinci is my iterator, consider it the "i" in the for loop
// at this point it has already been confirmed that both dbIncidents and tdIncidents have at least 1 entry thus using [0] won't give any problems
const db = _.first(fuse.search(tdIncidents[tdinci].id)),
td = tdIncidents[tdinci],
dbKeys = _.keys(dbIncidents[0]),
tdKeys = _.keys(tdIncidents[0]),
identicalKeysTd = _.pick(td, (value, key) => dbKeys.includes(key)),
identicalKeysDb = _.pick(db, (value, key) => tdKeys.includes(key));
相同的KeysDb将导致:
{ status: 'secondLine',
number: 'M1804 021',
request: '10-04-2018 21:02 Middelkoop, Paul: \nIk kan de servicedesk niet bereiken, telkens in gesprek',
briefDescription: 'Support niet bereikbaar',
externalNumber: '',
impact: null,
urgency: null,
priority: null,
duration: null,
targetDate: '2019-04-10T15:30:00.000+0000',
onHold: false,
onHoldDate: null,
onHoldDuration: 0,
feedbackMessage: null,
feedbackRating: null,
processingStatus: { id: '70b2967d-e248-4ff9-a632-ec044410d5a6', name: 'Afgemeld' },
completed: true,
completedDate: '2018-04-10T19:09:00.000+0000',
closed: true,
closedDate: '2018-04-10T19:12:00.000+0000',
closureCode: null,
timeSpent: 0,
timeSpentFirstLine: 0,
timeSpentSecondLineAndPartials: 0,
costs: 0,
escalationStatus: null,
escalationReason: null,
escalationOperator: null,
callDate: '2018-04-10T19:01:00.000+0000',
creationDate: '2018-04-10T19:02:34.000+0000',
modifier:
{ id: '226082ea-8d74-4dee-ae1e-74c33c883792',
name: 'Middelkoop, Paul' },
modificationDate: '2018-04-10T19:12:08.000+0000',
majorCall: false,
monitored: false,
expectedTimeSpent: 0,
archivingReason: null }
{ status: 'secondLine',
briefDescription: 'Support niet bereikbaar',
callDate: '2018-04-10T19:01:00.000Z',
number: 'M1804 021',
request: '10-04-2018 21:02 Middelkoop, Paul: \nIk kan de servicedesk niet bereiken, telkens in gesprek',
externalNumber: null,
impact: null,
urgency: null,
priority: null,
duration: null,
targetDate: '2019-04-10T15:30:00.000Z',
onHold: false,
onHoldDate: null,
onHoldDuration: 0,
feedbackMessage: null,
feedbackRating: null,
processingStatus: 'Afgemeld',
completed: true,
completedDate: '2018-04-10T19:09:00.000Z',
closed: true,
closedDate: null,
closureCode: null,
creationDate: '2018-04-10T19:02:34.000Z',
timeSpent: 0,
timeSpentFirstLine: 0,
timeSpentSecondLineAndPartials: 0,
costs: 0,
escalationStatus: null,
escalationReason: null,
escalationOperator: null,
modifier: '226082ea-8d74-4dee-ae1e-74c33c883792',
modificationDate: '2018-04-10T19:12:08.000Z',
expectedTimeSpent: 0,
majorCall: false,
monitored: false,
archivingReason: null }
(identicalKeys
)检查这两个.isEqual
对象是否相等,但无济于事。除了直接存储一些键而没有在数据库中附加“ID”的事实(这可以在数据库端修复),更紧迫的问题是数据库将为_.isEqual(identicalKeysDb, identicalKeysTd)
等值提供null
但是API会给externalNumber
。 在最近的尝试中,我在ES6,普通JS和UnderscoreJS中尝试了很多其他功能(太多不能提及和代码已经被删除,在我的“撤销”链上不再可用)但我找不到任何有效的功能方法,我真的真的不想硬编码一个巨大的''
来检查每个属性与其对应物。我不介意要求一些节点包使这个比较容易,所以如果这是解决方案,请分享它。
那些实际更改的对象我推送到一个名为if ()
的数组,后来随后会返回任何新事件。这发生如下:
existingIncidents
编辑:在底部添加了整个功能
最终编辑:我在这里将一个runkit链接转移到Nina Schulz的最终解决方案实现,因为我必须将其调整到我的确切用例并且分享是关心,也许它将来会帮助其他人。 永久链接:https://runkit.com/favna/so-compare-objects
答案 0 :(得分:1)
这是一种方法,通过对不同样式的对象使用数组以及每个对象的属性的相对路径。
关键功能是单个函数getValue
,它将对象和一组键引入所需属性,并返回找到的值或链的最后找到的值。
另一个函数迭代给定的关系对象,并显示(实际上)两个值用于计算和后续操作,如更新或其他想要的操作。
function getValue(object, keys) {
return keys.reduce((o, k) => o && typeof o === 'object' ? o[k] : o, object);
}
function compaire(objects, relations) {
relations.forEach(relation => {
var values = relation.map((keys, i) => getValue(objects[i], keys));
console.log(...values);
});
}
var objectA = { foo: { bar: 42 }, a: { b: { c: 'baz' } }, callerLocation: null },
objectB = { fooBar: 42, nested: { abc: 'bau' }, callerLocationID: null },
objects = [objectA, objectB],
relations = [
[['foo', 'bar'], ['fooBar']],
[['a', 'b', 'c'], ['nested', 'abc']],
[['callerLocation', 'id'], ['callerLocationID']],
[['x', 'u'], ['x', 'y']]
];
compaire(objects, relations);