mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-25 20:54:07 -08:00
✨ Add "mergeByIndex" option to Merge-Node
This commit is contained in:
parent
1b59d7b886
commit
88a82efe07
|
@ -34,8 +34,13 @@ export class Merge implements INodeType {
|
||||||
description: 'Combines data of both inputs. The output will contain items of input 1 and input 2.',
|
description: 'Combines data of both inputs. The output will contain items of input 1 and input 2.',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Merge',
|
name: 'Merge By Index',
|
||||||
value: 'merge',
|
value: 'mergeByIndex',
|
||||||
|
description: 'Merges data of both inputs. The output will contain items of input 1 merged with data of input 2. Merge happens depending on the index of the items. So first item of input 1 will be merged with first item of input 2 and so on.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Merge By Key',
|
||||||
|
value: 'mergeByKey',
|
||||||
description: 'Merges data of both inputs. The output will contain items of input 1 merged with data of input 2. Merge happens depending on a defined key.',
|
description: 'Merges data of both inputs. The output will contain items of input 1 merged with data of input 2. Merge happens depending on a defined key.',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -50,7 +55,38 @@ export class Merge implements INodeType {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
default: 'append',
|
default: 'append',
|
||||||
description: 'How data should be merged. If it should simply<br />be appended or merged depending on a property.',
|
description: 'How data of branches should be merged.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Join',
|
||||||
|
name: 'join',
|
||||||
|
type: 'options',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
mode: [
|
||||||
|
'mergeByIndex'
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: 'Inner Join',
|
||||||
|
value: 'inner',
|
||||||
|
description: 'Merges as many items as both inputs contain. (Example: Input1 = 5 items, Input2 = 3 items | Output will contain 3 items)',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Left Join',
|
||||||
|
value: 'left',
|
||||||
|
description: 'Merges as many items as first input contains. (Example: Input1 = 3 items, Input2 = 5 items | Output will contain 3 items)',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Outer Join',
|
||||||
|
value: 'outer',
|
||||||
|
description: 'Merges as many items as input contains with most items. (Example: Input1 = 3 items, Input2 = 5 items | Output will contain 5 items)',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
default: 'left',
|
||||||
|
description: 'How many items the output will contain<br />if inputs contain different amount of items.',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Property Input 1',
|
displayName: 'Property Input 1',
|
||||||
|
@ -61,7 +97,7 @@ export class Merge implements INodeType {
|
||||||
displayOptions: {
|
displayOptions: {
|
||||||
show: {
|
show: {
|
||||||
mode: [
|
mode: [
|
||||||
'merge'
|
'mergeByKey'
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -76,7 +112,7 @@ export class Merge implements INodeType {
|
||||||
displayOptions: {
|
displayOptions: {
|
||||||
show: {
|
show: {
|
||||||
mode: [
|
mode: [
|
||||||
'merge'
|
'mergeByKey'
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -122,7 +158,88 @@ export class Merge implements INodeType {
|
||||||
for (let i = 0; i < 2; i++) {
|
for (let i = 0; i < 2; i++) {
|
||||||
returnData.push.apply(returnData, this.getInputData(i));
|
returnData.push.apply(returnData, this.getInputData(i));
|
||||||
}
|
}
|
||||||
} else if (mode === 'merge') {
|
} else if (mode === 'mergeByIndex') {
|
||||||
|
// Merges data by index
|
||||||
|
|
||||||
|
const join = this.getNodeParameter('join', 0) as string;
|
||||||
|
|
||||||
|
const dataInput1 = this.getInputData(0);
|
||||||
|
const dataInput2 = this.getInputData(1);
|
||||||
|
|
||||||
|
if (dataInput1 === undefined || dataInput1.length === 0) {
|
||||||
|
if (['inner', 'left'].includes(join)) {
|
||||||
|
// When "inner" or "left" join return empty if first
|
||||||
|
// input does not contain any items
|
||||||
|
return [returnData];
|
||||||
|
}
|
||||||
|
|
||||||
|
// For "outer" return data of second input
|
||||||
|
return [dataInput2];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dataInput2 === undefined || dataInput2.length === 0) {
|
||||||
|
if (['left', 'outer'].includes(join)) {
|
||||||
|
// When "left" or "outer" join return data of first input
|
||||||
|
return [dataInput1];
|
||||||
|
}
|
||||||
|
|
||||||
|
// For "inner" return empty
|
||||||
|
return [returnData];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default "left"
|
||||||
|
let numEntries = dataInput1.length;
|
||||||
|
if (join === 'inner') {
|
||||||
|
numEntries = Math.min(dataInput1.length, dataInput2.length);
|
||||||
|
} else if (join === 'outer') {
|
||||||
|
numEntries = Math.max(dataInput1.length, dataInput2.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
let newItem: INodeExecutionData;
|
||||||
|
for (let i = 0; i < numEntries; i++) {
|
||||||
|
if (i >= dataInput1.length) {
|
||||||
|
returnData.push(dataInput2[i]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (i >= dataInput2.length) {
|
||||||
|
returnData.push(dataInput1[i]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
newItem = {
|
||||||
|
json: {},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (dataInput1[i].binary !== undefined) {
|
||||||
|
newItem.binary = {};
|
||||||
|
// Create a shallow copy of the binary data so that the old
|
||||||
|
// data references which do not get changed still stay behind
|
||||||
|
// but the incoming data does not get changed.
|
||||||
|
Object.assign(newItem.binary, dataInput1[i].binary);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create also a shallow copy of the json data
|
||||||
|
Object.assign(newItem.json, dataInput1[i].json);
|
||||||
|
|
||||||
|
// Copy json data
|
||||||
|
for (const key of Object.keys(dataInput2[i].json)) {
|
||||||
|
newItem.json[key] = dataInput2[i].json[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy binary data
|
||||||
|
if (dataInput2[i].binary !== undefined) {
|
||||||
|
if (newItem.binary === undefined) {
|
||||||
|
newItem.binary = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const key of Object.keys(dataInput2[i].binary!)) {
|
||||||
|
newItem.binary[key] = dataInput2[i].binary![key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
returnData.push(newItem);
|
||||||
|
}
|
||||||
|
} else if (mode === 'mergeByKey') {
|
||||||
// Merges data by key
|
// Merges data by key
|
||||||
const dataInput1 = this.getInputData(0);
|
const dataInput1 = this.getInputData(0);
|
||||||
if (!dataInput1) {
|
if (!dataInput1) {
|
||||||
|
|
Loading…
Reference in a new issue