mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-24 20:24:05 -08:00
feat(Merge Node)!: node tweaks n8n-4939 (#4321)
BREAKING CHANGE: The Merge node list of operations was rearranged. Merge node: 'Combine' operation was added with 'Combine Mode' option, operations 'Merge By Fields', 'Merge By Position' and 'Multiplex' placed under 'Combine Mode' option. To update -go to the workflows that use the Merge node, select 'Combine' operation and then choose an option from 'Combination Mode' that matches an operation that was previously used. If you want to continue even on error, you can set "Continue on Fail" to true.
This commit is contained in:
parent
1db4fa2bf8
commit
6a37071350
|
@ -2,6 +2,20 @@
|
||||||
|
|
||||||
This list shows all the versions which include breaking changes and how to upgrade.
|
This list shows all the versions which include breaking changes and how to upgrade.
|
||||||
|
|
||||||
|
## 0.198.0
|
||||||
|
|
||||||
|
### What changed?
|
||||||
|
|
||||||
|
The Merge node list of operations was rearranged.
|
||||||
|
|
||||||
|
### When is action necessary?
|
||||||
|
|
||||||
|
If you are using the overhauled Merge node and 'Merge By Fields', 'Merge By Position' or 'Multiplex' operation.
|
||||||
|
|
||||||
|
### How to upgrade:
|
||||||
|
|
||||||
|
Go to the workflows that use the Merge node, select 'Combine' operation and then choose an option from 'Combination Mode' that matches an operation that was previously used. If you want to continue even on error, you can set "Continue on Fail" to true.
|
||||||
|
|
||||||
## 0.171.0
|
## 0.171.0
|
||||||
|
|
||||||
### What changed?
|
### What changed?
|
||||||
|
|
|
@ -35,6 +35,7 @@ type MultipleMatches = 'all' | 'first';
|
||||||
export type MatchFieldsOutput = 'both' | 'input1' | 'input2';
|
export type MatchFieldsOutput = 'both' | 'input1' | 'input2';
|
||||||
|
|
||||||
export type MatchFieldsJoinMode =
|
export type MatchFieldsJoinMode =
|
||||||
|
| 'keepEverything'
|
||||||
| 'keepMatches'
|
| 'keepMatches'
|
||||||
| 'keepNonMatches'
|
| 'keepNonMatches'
|
||||||
| 'enrichInput2'
|
| 'enrichInput2'
|
||||||
|
@ -294,12 +295,16 @@ export function selectMergeMethod(clashResolveOptions: ClashResolveOptions) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mergeMode === 'deepMerge') {
|
if (mergeMode === 'deepMerge') {
|
||||||
return (target: IDataObject, ...source: IDataObject[]) =>
|
return (target: IDataObject, ...source: IDataObject[]) => {
|
||||||
mergeWith(target, ...source, customizer);
|
const targetCopy = Object.assign({}, target);
|
||||||
|
return mergeWith(targetCopy, ...source, customizer);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
if (mergeMode === 'shallowMerge') {
|
if (mergeMode === 'shallowMerge') {
|
||||||
return (target: IDataObject, ...source: IDataObject[]) =>
|
return (target: IDataObject, ...source: IDataObject[]) => {
|
||||||
assignWith(target, ...source, customizer);
|
const targetCopy = Object.assign({}, target);
|
||||||
|
return assignWith(targetCopy, ...source, customizer);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (mergeMode === 'deepMerge') {
|
if (mergeMode === 'deepMerge') {
|
||||||
|
|
|
@ -49,13 +49,31 @@ const versionDescription: INodeTypeDescription = {
|
||||||
displayName: 'Mode',
|
displayName: 'Mode',
|
||||||
name: 'mode',
|
name: 'mode',
|
||||||
type: 'options',
|
type: 'options',
|
||||||
// eslint-disable-next-line n8n-nodes-base/node-param-options-type-unsorted-items
|
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
name: 'Append',
|
name: 'Append',
|
||||||
value: 'append',
|
value: 'append',
|
||||||
description: 'All items of input 1, then all items of input 2',
|
description: 'All items of input 1, then all items of input 2',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'Combine',
|
||||||
|
value: 'combine',
|
||||||
|
description: 'Merge matching items together',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Choose Branch',
|
||||||
|
value: 'chooseBranch',
|
||||||
|
description: 'Output input data, without modifying it',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
default: 'append',
|
||||||
|
description: 'How data of branches should be merged',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Combination Mode',
|
||||||
|
name: 'combinationMode',
|
||||||
|
type: 'options',
|
||||||
|
options: [
|
||||||
{
|
{
|
||||||
name: 'Merge By Fields',
|
name: 'Merge By Fields',
|
||||||
value: 'mergeByFields',
|
value: 'mergeByFields',
|
||||||
|
@ -71,16 +89,14 @@ const versionDescription: INodeTypeDescription = {
|
||||||
value: 'multiplex',
|
value: 'multiplex',
|
||||||
description: 'All possible item combinations (cross join)',
|
description: 'All possible item combinations (cross join)',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: 'Choose Branch',
|
|
||||||
value: 'chooseBranch',
|
|
||||||
description: 'Output input data, without modifying it',
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
default: 'append',
|
default: 'mergeByFields',
|
||||||
description: 'How data of branches should be merged',
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
mode: ['combine'],
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
// mergeByFields ------------------------------------------------------------------
|
// mergeByFields ------------------------------------------------------------------
|
||||||
{
|
{
|
||||||
displayName: 'Fields to Match',
|
displayName: 'Fields to Match',
|
||||||
|
@ -119,7 +135,8 @@ const versionDescription: INodeTypeDescription = {
|
||||||
],
|
],
|
||||||
displayOptions: {
|
displayOptions: {
|
||||||
show: {
|
show: {
|
||||||
mode: ['mergeByFields'],
|
mode: ['combine'],
|
||||||
|
combinationMode: ['mergeByFields'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -127,6 +144,7 @@ const versionDescription: INodeTypeDescription = {
|
||||||
displayName: 'Output Type',
|
displayName: 'Output Type',
|
||||||
name: 'joinMode',
|
name: 'joinMode',
|
||||||
type: 'options',
|
type: 'options',
|
||||||
|
// eslint-disable-next-line n8n-nodes-base/node-param-options-type-unsorted-items
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
name: 'Keep Matches',
|
name: 'Keep Matches',
|
||||||
|
@ -136,7 +154,12 @@ const versionDescription: INodeTypeDescription = {
|
||||||
{
|
{
|
||||||
name: 'Keep Non-Matches',
|
name: 'Keep Non-Matches',
|
||||||
value: 'keepNonMatches',
|
value: 'keepNonMatches',
|
||||||
description: "Items that don't match (outer join)",
|
description: "Items that don't match",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Keep Everything',
|
||||||
|
value: 'keepEverything',
|
||||||
|
description: "Items that match merged together, plus items that don't match (outer join)",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Enrich Input 1',
|
name: 'Enrich Input 1',
|
||||||
|
@ -152,7 +175,8 @@ const versionDescription: INodeTypeDescription = {
|
||||||
default: 'keepMatches',
|
default: 'keepMatches',
|
||||||
displayOptions: {
|
displayOptions: {
|
||||||
show: {
|
show: {
|
||||||
mode: ['mergeByFields'],
|
mode: ['combine'],
|
||||||
|
combinationMode: ['mergeByFields'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -177,7 +201,8 @@ const versionDescription: INodeTypeDescription = {
|
||||||
default: 'both',
|
default: 'both',
|
||||||
displayOptions: {
|
displayOptions: {
|
||||||
show: {
|
show: {
|
||||||
mode: ['mergeByFields'],
|
mode: ['combine'],
|
||||||
|
combinationMode: ['mergeByFields'],
|
||||||
joinMode: ['keepMatches'],
|
joinMode: ['keepMatches'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -203,7 +228,8 @@ const versionDescription: INodeTypeDescription = {
|
||||||
default: 'both',
|
default: 'both',
|
||||||
displayOptions: {
|
displayOptions: {
|
||||||
show: {
|
show: {
|
||||||
mode: ['mergeByFields'],
|
mode: ['combine'],
|
||||||
|
combinationMode: ['mergeByFields'],
|
||||||
joinMode: ['keepNonMatches'],
|
joinMode: ['keepNonMatches'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -219,11 +245,6 @@ const versionDescription: INodeTypeDescription = {
|
||||||
name: 'Wait for Both Inputs to Arrive',
|
name: 'Wait for Both Inputs to Arrive',
|
||||||
value: 'waitForBoth',
|
value: 'waitForBoth',
|
||||||
},
|
},
|
||||||
// not MVP
|
|
||||||
// {
|
|
||||||
// name: 'Immediately Pass the First Input to Arrive',
|
|
||||||
// value: 'passFirst',
|
|
||||||
// },
|
|
||||||
],
|
],
|
||||||
default: 'waitForBoth',
|
default: 'waitForBoth',
|
||||||
displayOptions: {
|
displayOptions: {
|
||||||
|
@ -284,36 +305,116 @@ export class MergeV2 implements INodeType {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode === 'multiplex') {
|
if (mode === 'combine') {
|
||||||
const clashHandling = this.getNodeParameter(
|
const combinationMode = this.getNodeParameter('combinationMode', 0) as string;
|
||||||
'options.clashHandling.values',
|
|
||||||
0,
|
|
||||||
{},
|
|
||||||
) as ClashResolveOptions;
|
|
||||||
|
|
||||||
let input1 = this.getInputData(0);
|
if (combinationMode === 'multiplex') {
|
||||||
let input2 = this.getInputData(1);
|
const clashHandling = this.getNodeParameter(
|
||||||
|
'options.clashHandling.values',
|
||||||
|
0,
|
||||||
|
{},
|
||||||
|
) as ClashResolveOptions;
|
||||||
|
|
||||||
if (clashHandling.resolveClash === 'preferInput1') {
|
let input1 = this.getInputData(0);
|
||||||
[input1, input2] = [input2, input1];
|
let input2 = this.getInputData(1);
|
||||||
}
|
|
||||||
|
|
||||||
if (clashHandling.resolveClash === 'addSuffix') {
|
if (clashHandling.resolveClash === 'preferInput1') {
|
||||||
input1 = addSuffixToEntriesKeys(input1, '1');
|
[input1, input2] = [input2, input1];
|
||||||
input2 = addSuffixToEntriesKeys(input2, '2');
|
}
|
||||||
}
|
|
||||||
|
|
||||||
const mergeIntoSingleObject = selectMergeMethod(clashHandling);
|
if (clashHandling.resolveClash === 'addSuffix') {
|
||||||
|
input1 = addSuffixToEntriesKeys(input1, '1');
|
||||||
|
input2 = addSuffixToEntriesKeys(input2, '2');
|
||||||
|
}
|
||||||
|
|
||||||
if (!input1 || !input2) {
|
const mergeIntoSingleObject = selectMergeMethod(clashHandling);
|
||||||
|
|
||||||
|
if (!input1 || !input2) {
|
||||||
|
return [returnData];
|
||||||
|
}
|
||||||
|
|
||||||
|
let entry1: INodeExecutionData;
|
||||||
|
let entry2: INodeExecutionData;
|
||||||
|
|
||||||
|
for (entry1 of input1) {
|
||||||
|
for (entry2 of input2) {
|
||||||
|
returnData.push({
|
||||||
|
json: {
|
||||||
|
...mergeIntoSingleObject(entry1.json, entry2.json),
|
||||||
|
},
|
||||||
|
binary: {
|
||||||
|
...merge({}, entry1.binary, entry2.binary),
|
||||||
|
},
|
||||||
|
pairedItem: [
|
||||||
|
entry1.pairedItem as IPairedItemData,
|
||||||
|
entry2.pairedItem as IPairedItemData,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
return [returnData];
|
return [returnData];
|
||||||
}
|
}
|
||||||
|
|
||||||
let entry1: INodeExecutionData;
|
if (combinationMode === 'mergeByPosition') {
|
||||||
let entry2: INodeExecutionData;
|
const clashHandling = this.getNodeParameter(
|
||||||
|
'options.clashHandling.values',
|
||||||
|
0,
|
||||||
|
{},
|
||||||
|
) as ClashResolveOptions;
|
||||||
|
const includeUnpaired = this.getNodeParameter(
|
||||||
|
'options.includeUnpaired',
|
||||||
|
0,
|
||||||
|
false,
|
||||||
|
) as boolean;
|
||||||
|
|
||||||
|
let input1 = this.getInputData(0);
|
||||||
|
let input2 = this.getInputData(1);
|
||||||
|
|
||||||
|
if (clashHandling.resolveClash === 'preferInput1') {
|
||||||
|
[input1, input2] = [input2, input1];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clashHandling.resolveClash === 'addSuffix') {
|
||||||
|
input1 = addSuffixToEntriesKeys(input1, '1');
|
||||||
|
input2 = addSuffixToEntriesKeys(input2, '2');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input1 === undefined || input1.length === 0) {
|
||||||
|
if (includeUnpaired) {
|
||||||
|
return [input2];
|
||||||
|
}
|
||||||
|
return [returnData];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input2 === undefined || input2.length === 0) {
|
||||||
|
if (includeUnpaired) {
|
||||||
|
return [input1];
|
||||||
|
}
|
||||||
|
return [returnData];
|
||||||
|
}
|
||||||
|
|
||||||
|
let numEntries: number;
|
||||||
|
if (includeUnpaired) {
|
||||||
|
numEntries = Math.max(input1.length, input2.length);
|
||||||
|
} else {
|
||||||
|
numEntries = Math.min(input1.length, input2.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
const mergeIntoSingleObject = selectMergeMethod(clashHandling);
|
||||||
|
|
||||||
|
for (let i = 0; i < numEntries; i++) {
|
||||||
|
if (i >= input1.length) {
|
||||||
|
returnData.push(input2[i]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (i >= input2.length) {
|
||||||
|
returnData.push(input1[i]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const entry1 = input1[i];
|
||||||
|
const entry2 = input2[i];
|
||||||
|
|
||||||
for (entry1 of input1) {
|
|
||||||
for (entry2 of input2) {
|
|
||||||
returnData.push({
|
returnData.push({
|
||||||
json: {
|
json: {
|
||||||
...mergeIntoSingleObject(entry1.json, entry2.json),
|
...mergeIntoSingleObject(entry1.json, entry2.json),
|
||||||
|
@ -328,162 +429,115 @@ export class MergeV2 implements INodeType {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return [returnData];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mode === 'mergeByPosition') {
|
if (combinationMode === 'mergeByFields') {
|
||||||
const clashHandling = this.getNodeParameter(
|
const matchFields = checkMatchFieldsInput(
|
||||||
'options.clashHandling.values',
|
this.getNodeParameter('mergeByFields.values', 0, []) as IDataObject[],
|
||||||
0,
|
);
|
||||||
{},
|
|
||||||
) as ClashResolveOptions;
|
|
||||||
const includeUnpaired = this.getNodeParameter('options.includeUnpaired', 0, false) as boolean;
|
|
||||||
|
|
||||||
let input1 = this.getInputData(0);
|
const joinMode = this.getNodeParameter('joinMode', 0) as MatchFieldsJoinMode;
|
||||||
let input2 = this.getInputData(1);
|
const outputDataFrom = this.getNodeParameter(
|
||||||
|
'outputDataFrom',
|
||||||
|
0,
|
||||||
|
'both',
|
||||||
|
) as MatchFieldsOutput;
|
||||||
|
const options = this.getNodeParameter('options', 0, {}) as MatchFieldsOptions;
|
||||||
|
|
||||||
if (clashHandling.resolveClash === 'preferInput1') {
|
options.joinMode = joinMode;
|
||||||
[input1, input2] = [input2, input1];
|
options.outputDataFrom = outputDataFrom;
|
||||||
}
|
|
||||||
|
|
||||||
if (clashHandling.resolveClash === 'addSuffix') {
|
const input1 = checkInput(
|
||||||
input1 = addSuffixToEntriesKeys(input1, '1');
|
this.getInputData(0),
|
||||||
input2 = addSuffixToEntriesKeys(input2, '2');
|
matchFields.map((pair) => pair.field1 as string),
|
||||||
}
|
(options.disableDotNotation as boolean) || false,
|
||||||
|
'Input 1',
|
||||||
|
);
|
||||||
|
if (!input1) return [returnData];
|
||||||
|
|
||||||
if (input1 === undefined || input1.length === 0) {
|
const input2 = checkInput(
|
||||||
if (includeUnpaired) {
|
this.getInputData(1),
|
||||||
return [input2];
|
matchFields.map((pair) => pair.field2 as string),
|
||||||
}
|
(options.disableDotNotation as boolean) || false,
|
||||||
return [returnData];
|
'Input 2',
|
||||||
}
|
);
|
||||||
|
|
||||||
if (input2 === undefined || input2.length === 0) {
|
if (!input2 || !matchFields.length) {
|
||||||
if (includeUnpaired) {
|
if (
|
||||||
|
joinMode === 'keepMatches' ||
|
||||||
|
joinMode === 'keepEverything' ||
|
||||||
|
joinMode === 'enrichInput2'
|
||||||
|
) {
|
||||||
|
return [returnData];
|
||||||
|
}
|
||||||
return [input1];
|
return [input1];
|
||||||
}
|
}
|
||||||
return [returnData];
|
|
||||||
}
|
|
||||||
|
|
||||||
let numEntries: number;
|
const matches = findMatches(input1, input2, matchFields, options);
|
||||||
if (includeUnpaired) {
|
|
||||||
numEntries = Math.max(input1.length, input2.length);
|
|
||||||
} else {
|
|
||||||
numEntries = Math.min(input1.length, input2.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
const mergeIntoSingleObject = selectMergeMethod(clashHandling);
|
if (joinMode === 'keepMatches' || joinMode === 'keepEverything') {
|
||||||
|
let output: INodeExecutionData[] = [];
|
||||||
for (let i = 0; i < numEntries; i++) {
|
|
||||||
if (i >= input1.length) {
|
|
||||||
returnData.push(input2[i]);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (i >= input2.length) {
|
|
||||||
returnData.push(input1[i]);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const entry1 = input1[i];
|
|
||||||
const entry2 = input2[i];
|
|
||||||
|
|
||||||
returnData.push({
|
|
||||||
json: {
|
|
||||||
...mergeIntoSingleObject(entry1.json, entry2.json),
|
|
||||||
},
|
|
||||||
binary: {
|
|
||||||
...merge({}, entry1.binary, entry2.binary),
|
|
||||||
},
|
|
||||||
pairedItem: [entry1.pairedItem as IPairedItemData, entry2.pairedItem as IPairedItemData],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mode === 'mergeByFields') {
|
|
||||||
const matchFields = checkMatchFieldsInput(
|
|
||||||
this.getNodeParameter('mergeByFields.values', 0, []) as IDataObject[],
|
|
||||||
);
|
|
||||||
|
|
||||||
const joinMode = this.getNodeParameter('joinMode', 0) as MatchFieldsJoinMode;
|
|
||||||
const outputDataFrom = this.getNodeParameter('outputDataFrom', 0, '') as MatchFieldsOutput;
|
|
||||||
const options = this.getNodeParameter('options', 0, {}) as MatchFieldsOptions;
|
|
||||||
|
|
||||||
options.joinMode = joinMode;
|
|
||||||
options.outputDataFrom = outputDataFrom;
|
|
||||||
|
|
||||||
const input1 = checkInput(
|
|
||||||
this.getInputData(0),
|
|
||||||
matchFields.map((pair) => pair.field1 as string),
|
|
||||||
(options.disableDotNotation as boolean) || false,
|
|
||||||
'Input 1',
|
|
||||||
);
|
|
||||||
if (!input1) return [returnData];
|
|
||||||
|
|
||||||
const input2 = checkInput(
|
|
||||||
this.getInputData(1),
|
|
||||||
matchFields.map((pair) => pair.field2 as string),
|
|
||||||
(options.disableDotNotation as boolean) || false,
|
|
||||||
'Input 2',
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!input2 || !matchFields.length) {
|
|
||||||
if (joinMode === 'keepMatches' || joinMode === 'enrichInput2') {
|
|
||||||
return [returnData];
|
|
||||||
}
|
|
||||||
return [input1];
|
|
||||||
}
|
|
||||||
|
|
||||||
const matches = findMatches(input1, input2, matchFields, options);
|
|
||||||
|
|
||||||
if (joinMode === 'keepMatches') {
|
|
||||||
if (outputDataFrom === 'input1') {
|
|
||||||
return [matches.matched.map((match) => match.entry)];
|
|
||||||
}
|
|
||||||
if (outputDataFrom === 'input2') {
|
|
||||||
return [matches.matched2];
|
|
||||||
}
|
|
||||||
if (outputDataFrom === 'both') {
|
|
||||||
const clashResolveOptions = this.getNodeParameter(
|
const clashResolveOptions = this.getNodeParameter(
|
||||||
'options.clashHandling.values',
|
'options.clashHandling.values',
|
||||||
0,
|
0,
|
||||||
{},
|
{},
|
||||||
) as ClashResolveOptions;
|
) as ClashResolveOptions;
|
||||||
|
|
||||||
const mergedEntries = mergeMatched(matches.matched, clashResolveOptions);
|
if (outputDataFrom === 'input1') {
|
||||||
|
output = matches.matched.map((match) => match.entry);
|
||||||
|
}
|
||||||
|
if (outputDataFrom === 'input2') {
|
||||||
|
output = matches.matched2;
|
||||||
|
}
|
||||||
|
if (outputDataFrom === 'both') {
|
||||||
|
output = mergeMatched(matches.matched, clashResolveOptions);
|
||||||
|
}
|
||||||
|
|
||||||
returnData.push(...mergedEntries);
|
if (joinMode === 'keepEverything') {
|
||||||
|
let unmatched1 = matches.unmatched1;
|
||||||
|
let unmatched2 = matches.unmatched2;
|
||||||
|
if (clashResolveOptions.resolveClash === 'addSuffix') {
|
||||||
|
unmatched1 = addSuffixToEntriesKeys(unmatched1, '1');
|
||||||
|
unmatched2 = addSuffixToEntriesKeys(unmatched2, '2');
|
||||||
|
}
|
||||||
|
output = [...output, ...unmatched1, ...unmatched2];
|
||||||
|
}
|
||||||
|
|
||||||
|
returnData.push(...output);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (joinMode === 'keepNonMatches') {
|
if (joinMode === 'keepNonMatches') {
|
||||||
if (outputDataFrom === 'input1') {
|
if (outputDataFrom === 'input1') {
|
||||||
return [matches.unmatched1];
|
return [matches.unmatched1];
|
||||||
|
}
|
||||||
|
if (outputDataFrom === 'input2') {
|
||||||
|
return [matches.unmatched2];
|
||||||
|
}
|
||||||
|
if (outputDataFrom === 'both') {
|
||||||
|
let output: INodeExecutionData[] = [];
|
||||||
|
output = output.concat(addSourceField(matches.unmatched1, 'input1'));
|
||||||
|
output = output.concat(addSourceField(matches.unmatched2, 'input2'));
|
||||||
|
return [output];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (outputDataFrom === 'input2') {
|
|
||||||
return [matches.unmatched2];
|
|
||||||
}
|
|
||||||
if (outputDataFrom === 'both') {
|
|
||||||
let output: INodeExecutionData[] = [];
|
|
||||||
output = output.concat(addSourceField(matches.unmatched1, 'input1'));
|
|
||||||
output = output.concat(addSourceField(matches.unmatched2, 'input2'));
|
|
||||||
return [output];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (joinMode === 'enrichInput1' || joinMode === 'enrichInput2') {
|
if (joinMode === 'enrichInput1' || joinMode === 'enrichInput2') {
|
||||||
const clashResolveOptions = this.getNodeParameter(
|
const clashResolveOptions = this.getNodeParameter(
|
||||||
'options.clashHandling.values',
|
'options.clashHandling.values',
|
||||||
0,
|
0,
|
||||||
{},
|
{},
|
||||||
) as ClashResolveOptions;
|
) as ClashResolveOptions;
|
||||||
|
|
||||||
const mergedEntries = mergeMatched(matches.matched, clashResolveOptions, joinMode);
|
const mergedEntries = mergeMatched(matches.matched, clashResolveOptions, joinMode);
|
||||||
|
|
||||||
if (clashResolveOptions.resolveClash === 'addSuffix') {
|
if (clashResolveOptions.resolveClash === 'addSuffix') {
|
||||||
const suffix = joinMode === 'enrichInput1' ? '1' : '2';
|
const suffix = joinMode === 'enrichInput1' ? '1' : '2';
|
||||||
returnData.push(...mergedEntries, ...addSuffixToEntriesKeys(matches.unmatched1, suffix));
|
returnData.push(
|
||||||
} else {
|
...mergedEntries,
|
||||||
returnData.push(...mergedEntries, ...matches.unmatched1);
|
...addSuffixToEntriesKeys(matches.unmatched1, suffix),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
returnData.push(...mergedEntries, ...matches.unmatched1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,7 +87,8 @@ export const optionsDescription: INodeProperties[] = [
|
||||||
...clashHandlingProperties,
|
...clashHandlingProperties,
|
||||||
displayOptions: {
|
displayOptions: {
|
||||||
show: {
|
show: {
|
||||||
'/mode': ['mergeByFields'],
|
'/mode': ['combine'],
|
||||||
|
'/combinationMode': ['mergeByFields'],
|
||||||
},
|
},
|
||||||
hide: {
|
hide: {
|
||||||
'/joinMode': ['keepMatches', 'keepNonMatches'],
|
'/joinMode': ['keepMatches', 'keepNonMatches'],
|
||||||
|
@ -98,7 +99,8 @@ export const optionsDescription: INodeProperties[] = [
|
||||||
...clashHandlingProperties,
|
...clashHandlingProperties,
|
||||||
displayOptions: {
|
displayOptions: {
|
||||||
show: {
|
show: {
|
||||||
'/mode': ['mergeByFields'],
|
'/mode': ['combine'],
|
||||||
|
'/combinationMode': ['mergeByFields'],
|
||||||
'/joinMode': ['keepMatches'],
|
'/joinMode': ['keepMatches'],
|
||||||
'/outputDataFrom': ['both'],
|
'/outputDataFrom': ['both'],
|
||||||
},
|
},
|
||||||
|
@ -108,7 +110,8 @@ export const optionsDescription: INodeProperties[] = [
|
||||||
...clashHandlingProperties,
|
...clashHandlingProperties,
|
||||||
displayOptions: {
|
displayOptions: {
|
||||||
show: {
|
show: {
|
||||||
'/mode': ['multiplex', 'mergeByPosition'],
|
'/mode': ['combine'],
|
||||||
|
'/combinationMode': ['multiplex', 'mergeByPosition'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -121,7 +124,8 @@ export const optionsDescription: INodeProperties[] = [
|
||||||
'Whether to disallow referencing child fields using `parent.child` in the field name',
|
'Whether to disallow referencing child fields using `parent.child` in the field name',
|
||||||
displayOptions: {
|
displayOptions: {
|
||||||
show: {
|
show: {
|
||||||
'/mode': ['mergeByFields'],
|
'/mode': ['combine'],
|
||||||
|
'/combinationMode': ['mergeByFields'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -135,7 +139,8 @@ export const optionsDescription: INodeProperties[] = [
|
||||||
'If there are different numbers of items in input 1 and input 2, whether to include the ones at the end with nothing to pair with',
|
'If there are different numbers of items in input 1 and input 2, whether to include the ones at the end with nothing to pair with',
|
||||||
displayOptions: {
|
displayOptions: {
|
||||||
show: {
|
show: {
|
||||||
'/mode': ['mergeByPosition'],
|
'/mode': ['combine'],
|
||||||
|
'/combinationMode': ['mergeByPosition'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -158,7 +163,8 @@ export const optionsDescription: INodeProperties[] = [
|
||||||
],
|
],
|
||||||
displayOptions: {
|
displayOptions: {
|
||||||
show: {
|
show: {
|
||||||
'/mode': ['mergeByFields'],
|
'/mode': ['combine'],
|
||||||
|
'/combinationMode': ['mergeByFields'],
|
||||||
'/joinMode': ['keepMatches'],
|
'/joinMode': ['keepMatches'],
|
||||||
'/outputDataFrom': ['both'],
|
'/outputDataFrom': ['both'],
|
||||||
},
|
},
|
||||||
|
@ -183,8 +189,9 @@ export const optionsDescription: INodeProperties[] = [
|
||||||
],
|
],
|
||||||
displayOptions: {
|
displayOptions: {
|
||||||
show: {
|
show: {
|
||||||
'/mode': ['mergeByFields'],
|
'/mode': ['combine'],
|
||||||
'/joinMode': ['enrichInput1', 'enrichInput2'],
|
'/combinationMode': ['mergeByFields'],
|
||||||
|
'/joinMode': ['enrichInput1', 'enrichInput2', 'keepEverything'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue