mirror of
https://github.com/n8n-io/n8n.git
synced 2025-01-25 19:41:14 -08:00
feat(Compare Datasets Node): Node tweaks
This commit is contained in:
parent
402b75ac28
commit
423ee81e33
|
@ -13,10 +13,10 @@ export class CompareDatasets implements INodeType {
|
||||||
defaults: { name: 'Compare Datasets' },
|
defaults: { name: 'Compare Datasets' },
|
||||||
// eslint-disable-next-line n8n-nodes-base/node-class-description-inputs-wrong-regular-node
|
// eslint-disable-next-line n8n-nodes-base/node-class-description-inputs-wrong-regular-node
|
||||||
inputs: ['main', 'main'],
|
inputs: ['main', 'main'],
|
||||||
inputNames: ['Input 1', 'Input 2'],
|
inputNames: ['Input A', 'Input B'],
|
||||||
// eslint-disable-next-line n8n-nodes-base/node-class-description-outputs-wrong
|
// eslint-disable-next-line n8n-nodes-base/node-class-description-outputs-wrong
|
||||||
outputs: ['main', 'main', 'main', 'main'],
|
outputs: ['main', 'main', 'main', 'main'],
|
||||||
outputNames: ['In 1 only', 'Same', 'Different', 'In 2 only'],
|
outputNames: ['In A only', 'Same', 'Different', 'In B only'],
|
||||||
properties: [
|
properties: [
|
||||||
{
|
{
|
||||||
displayName: 'Fields to Match',
|
displayName: 'Fields to Match',
|
||||||
|
@ -33,7 +33,7 @@ export class CompareDatasets implements INodeType {
|
||||||
name: 'values',
|
name: 'values',
|
||||||
values: [
|
values: [
|
||||||
{
|
{
|
||||||
displayName: 'Input 1 Field',
|
displayName: 'Input A Field',
|
||||||
name: 'field1',
|
name: 'field1',
|
||||||
type: 'string',
|
type: 'string',
|
||||||
default: '',
|
default: '',
|
||||||
|
@ -42,7 +42,7 @@ export class CompareDatasets implements INodeType {
|
||||||
hint: ' Enter the field name as text',
|
hint: ' Enter the field name as text',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Input 2 Field',
|
displayName: 'Input B Field',
|
||||||
name: 'field2',
|
name: 'field2',
|
||||||
type: 'string',
|
type: 'string',
|
||||||
default: '',
|
default: '',
|
||||||
|
@ -61,11 +61,11 @@ export class CompareDatasets implements INodeType {
|
||||||
default: 'preferInput2',
|
default: 'preferInput2',
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
name: 'Use Input 1 Version',
|
name: 'Use Input A Version',
|
||||||
value: 'preferInput1',
|
value: 'preferInput1',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Use Input 2 Version',
|
name: 'Use Input B Version',
|
||||||
value: 'preferInput2',
|
value: 'preferInput2',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -87,11 +87,11 @@ export class CompareDatasets implements INodeType {
|
||||||
default: 'input1',
|
default: 'input1',
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
name: 'Input 1 Version',
|
name: 'Input A Version',
|
||||||
value: 'input1',
|
value: 'input1',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Input 2 Version',
|
name: 'Input B Version',
|
||||||
value: 'input2',
|
value: 'input2',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -107,7 +107,7 @@ export class CompareDatasets implements INodeType {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
default: '',
|
default: '',
|
||||||
// eslint-disable-next-line n8n-nodes-base/node-param-placeholder-miscased-id
|
// eslint-disable-next-line n8n-nodes-base/node-param-placeholder-miscased-id
|
||||||
placeholder: 'e.d. id, country',
|
placeholder: 'e.g. id, country',
|
||||||
hint: 'Enter the names of the input fields as text, separated by commas',
|
hint: 'Enter the names of the input fields as text, separated by commas',
|
||||||
displayOptions: {
|
displayOptions: {
|
||||||
show: {
|
show: {
|
||||||
|
@ -122,6 +122,16 @@ export class CompareDatasets implements INodeType {
|
||||||
placeholder: 'Add Option',
|
placeholder: 'Add Option',
|
||||||
default: {},
|
default: {},
|
||||||
options: [
|
options: [
|
||||||
|
{
|
||||||
|
displayName: 'Fields to Skip Comparing',
|
||||||
|
name: 'skipFields',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
placeholder: 'e.g. updated_at, updated_by',
|
||||||
|
hint: 'Enter the field names as text, separated by commas',
|
||||||
|
description:
|
||||||
|
"Fields that shouldn't be included when checking whether two items are the same",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Disable Dot Notation',
|
displayName: 'Disable Dot Notation',
|
||||||
name: 'disableDotNotation',
|
name: 'disableDotNotation',
|
||||||
|
@ -164,14 +174,14 @@ export class CompareDatasets implements INodeType {
|
||||||
this.getInputData(0),
|
this.getInputData(0),
|
||||||
matchFields.map((pair) => pair.field1 as string),
|
matchFields.map((pair) => pair.field1 as string),
|
||||||
(options.disableDotNotation as boolean) || false,
|
(options.disableDotNotation as boolean) || false,
|
||||||
'Input 1',
|
'Input A',
|
||||||
);
|
);
|
||||||
|
|
||||||
const input2 = checkInput(
|
const input2 = checkInput(
|
||||||
this.getInputData(1),
|
this.getInputData(1),
|
||||||
matchFields.map((pair) => pair.field2 as string),
|
matchFields.map((pair) => pair.field2 as string),
|
||||||
(options.disableDotNotation as boolean) || false,
|
(options.disableDotNotation as boolean) || false,
|
||||||
'Input 2',
|
'Input B',
|
||||||
);
|
);
|
||||||
|
|
||||||
const resolve = this.getNodeParameter('resolve', 0, '') as string;
|
const resolve = this.getNodeParameter('resolve', 0, '') as string;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { IDataObject, INodeExecutionData } from 'n8n-workflow';
|
import { IDataObject, INodeExecutionData } from 'n8n-workflow';
|
||||||
import { difference, get, intersection, isEmpty, isEqual, set, union } from 'lodash';
|
import { difference, get, intersection, isEmpty, isEqual, omit, set, union } from 'lodash';
|
||||||
|
|
||||||
type PairToMatch = {
|
type PairToMatch = {
|
||||||
field1: string;
|
field1: string;
|
||||||
|
@ -15,7 +15,8 @@ function compareItems(
|
||||||
item1: INodeExecutionData,
|
item1: INodeExecutionData,
|
||||||
item2: INodeExecutionData,
|
item2: INodeExecutionData,
|
||||||
fieldsToMatch: PairToMatch[],
|
fieldsToMatch: PairToMatch[],
|
||||||
resolve?: string,
|
resolve: string,
|
||||||
|
skipFields: string[],
|
||||||
) {
|
) {
|
||||||
const keys = {} as IDataObject;
|
const keys = {} as IDataObject;
|
||||||
fieldsToMatch.forEach((field) => {
|
fieldsToMatch.forEach((field) => {
|
||||||
|
@ -38,6 +39,7 @@ function compareItems(
|
||||||
const differentKeys = difference(allUniqueKeys, sameKeys);
|
const differentKeys = difference(allUniqueKeys, sameKeys);
|
||||||
|
|
||||||
const different: IDataObject = {};
|
const different: IDataObject = {};
|
||||||
|
const skipped: IDataObject = {};
|
||||||
|
|
||||||
differentKeys.forEach((key) => {
|
differentKeys.forEach((key) => {
|
||||||
switch (resolve) {
|
switch (resolve) {
|
||||||
|
@ -50,11 +52,17 @@ function compareItems(
|
||||||
default:
|
default:
|
||||||
const input1 = item1.json[key] || null;
|
const input1 = item1.json[key] || null;
|
||||||
const input2 = item2.json[key] || null;
|
const input2 = item2.json[key] || null;
|
||||||
different[key] = { input1, input2 };
|
if (skipFields.includes(key)) {
|
||||||
|
skipped[key] = { input1, input2 };
|
||||||
|
} else {
|
||||||
|
different[key] = { input1, input2 };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return { json: { keys, same, different } } as INodeExecutionData;
|
return {
|
||||||
|
json: { keys, same, different, ...(!isEmpty(skipped) && { skipped }) },
|
||||||
|
} as INodeExecutionData;
|
||||||
}
|
}
|
||||||
|
|
||||||
function combineItems(
|
function combineItems(
|
||||||
|
@ -157,6 +165,7 @@ export function findMatches(
|
||||||
|
|
||||||
const disableDotNotation = (options.disableDotNotation as boolean) || false;
|
const disableDotNotation = (options.disableDotNotation as boolean) || false;
|
||||||
const multipleMatches = (options.multipleMatches as string) || 'first';
|
const multipleMatches = (options.multipleMatches as string) || 'first';
|
||||||
|
const skipFields = ((options.skipFields as string) || '').split(',').map((field) => field.trim());
|
||||||
|
|
||||||
const filteredData = {
|
const filteredData = {
|
||||||
matched: [] as EntryMatches[],
|
matched: [] as EntryMatches[],
|
||||||
|
@ -214,7 +223,14 @@ export function findMatches(
|
||||||
let entryCopy: INodeExecutionData | undefined;
|
let entryCopy: INodeExecutionData | undefined;
|
||||||
|
|
||||||
entryMatches.matches.forEach((match) => {
|
entryMatches.matches.forEach((match) => {
|
||||||
if (isEqual(entryMatches.entry.json, match.json)) {
|
let entryFromInput1 = entryMatches.entry.json;
|
||||||
|
let entryFromInput2 = match.json;
|
||||||
|
|
||||||
|
if (skipFields.length) {
|
||||||
|
entryFromInput1 = omit(entryFromInput1, skipFields);
|
||||||
|
entryFromInput2 = omit(entryFromInput2, skipFields);
|
||||||
|
}
|
||||||
|
if (isEqual(entryFromInput1, entryFromInput2)) {
|
||||||
if (!entryCopy) entryCopy = match;
|
if (!entryCopy) entryCopy = match;
|
||||||
} else {
|
} else {
|
||||||
switch (options.resolve) {
|
switch (options.resolve) {
|
||||||
|
@ -237,7 +253,13 @@ export function findMatches(
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
different.push(
|
different.push(
|
||||||
compareItems(entryMatches.entry, match, fieldsToMatch, options.resolve as string),
|
compareItems(
|
||||||
|
entryMatches.entry,
|
||||||
|
match,
|
||||||
|
fieldsToMatch,
|
||||||
|
options.resolve as string,
|
||||||
|
skipFields,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -274,6 +296,12 @@ export function checkInput(
|
||||||
disableDotNotation: boolean,
|
disableDotNotation: boolean,
|
||||||
inputLabel: string,
|
inputLabel: string,
|
||||||
) {
|
) {
|
||||||
|
if (input.some((item) => isEmpty(item.json))) {
|
||||||
|
input = input.filter((item) => !isEmpty(item.json));
|
||||||
|
}
|
||||||
|
if (input.length === 0) {
|
||||||
|
return input;
|
||||||
|
}
|
||||||
for (const field of fields) {
|
for (const field of fields) {
|
||||||
const isPresent = (input || []).some((entry) => {
|
const isPresent = (input || []).some((entry) => {
|
||||||
if (disableDotNotation) {
|
if (disableDotNotation) {
|
||||||
|
|
Loading…
Reference in a new issue