Hi all, I’m just getting started with n8n. I’m trying to learn how to pass data around as I need. To illustrate my problem, I have a practical example.
In my example, I’m adding all tracks from a Spotify playlist to a different playlist. Rather than using a static playlist URI for the target playlist though, I’m trying to find it based on its name. This example is a bit contrived because the name is simply set in a function node, but for my real-world workflow, the name will be generated programmatically.
I’m not sure I have the best approach for patching the target playlist URI into the Playlist ID parameter of the ‘Save to Target Playlist’ node. I would have expected I could reference the output of the function node in my ‘Save to Target Playlist’ parameter, but it can’t seem to find it. Instead, I’m merging a new property into each track record. This feels a bit hacky and I’m wondering if there’s something I’m missing.
Thanks so much for your work on n8n! It’s incredibly promising and I hope to be able to contribute once I learn more about it, brush up on my JavaScript, and finally learn TypeScript.
Here’s my workflow:
{
"name": "Spotify: Archive Playlist Example",
"nodes": [
{
"parameters": {},
"name": "Start",
"type": "n8n-nodes-base.start",
"typeVersion": 1,
"position": [
650,
450
]
},
{
"parameters": {
"triggerTimes": {
"item": [
{
"mode": "custom",
"cronExpression": "0 0 6 * * 1"
}
]
}
},
"name": "Cron",
"type": "n8n-nodes-base.cron",
"typeVersion": 1,
"position": [
850,
450
],
"notesInFlow": true,
"notes": "6am on Mondays"
},
{
"parameters": {
"mode": "multiplex"
},
"name": "Merge",
"type": "n8n-nodes-base.merge",
"typeVersion": 1,
"position": [
1650,
630
]
},
{
"parameters": {
"keepOnlySet": true,
"values": {
"string": [
{
"name": "targetPlaylist",
"value": "={{$json[\"uri\"]}}"
}
]
},
"options": {}
},
"name": "Set Target Playlist",
"type": "n8n-nodes-base.set",
"typeVersion": 1,
"position": [
1450,
450
]
},
{
"parameters": {
"functionCode": "//let playlistName = \"Discover Weekly Comprehensive\";\nlet playlistName = \"test playlist 1\";\n\nreturn items.filter((item) => {\n return item.json.name == playlistName;\n});\n"
},
"name": "Find Target Playlist",
"type": "n8n-nodes-base.function",
"typeVersion": 1,
"position": [
1250,
450
]
},
{
"parameters": {
"resource": "playlist",
"id": "={{$json[\"targetPlaylist\"]}}",
"trackID": "={{$json[\"track\"][\"uri\"]}}"
},
"name": "Save to Target Playlist",
"type": "n8n-nodes-base.spotify",
"typeVersion": 1,
"position": [
1850,
630
],
"credentials": {
"spotifyOAuth2Api": "Trey"
}
},
{
"parameters": {
"resource": "playlist",
"operation": "getUserPlaylists",
"returnAll": true
},
"name": "Get All Playlists",
"type": "n8n-nodes-base.spotify",
"typeVersion": 1,
"position": [
1050,
450
],
"credentials": {
"spotifyOAuth2Api": "Trey"
}
},
{
"parameters": {
"resource": "playlist",
"operation": "getTracks",
"id": "spotify:playlist:37i9dQZEVXcU9MVTlTbyiM",
"returnAll": true
},
"name": "Get Tracks From Source Playlist",
"type": "n8n-nodes-base.spotify",
"typeVersion": 1,
"position": [
1050,
650
],
"alwaysOutputData": false,
"credentials": {
"spotifyOAuth2Api": "Trey"
}
}
],
"connections": {
"Cron": {
"main": [
[
{
"node": "Get All Playlists",
"type": "main",
"index": 0
},
{
"node": "Get Tracks From Source Playlist",
"type": "main",
"index": 0
}
]
]
},
"Merge": {
"main": [
[
{
"node": "Save to Target Playlist",
"type": "main",
"index": 0
}
]
]
},
"Set Target Playlist": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 0
}
]
]
},
"Find Target Playlist": {
"main": [
[
{
"node": "Set Target Playlist",
"type": "main",
"index": 0
}
]
]
},
"Get All Playlists": {
"main": [
[
{
"node": "Find Target Playlist",
"type": "main",
"index": 0
}
]
]
},
"Get Tracks From Source Playlist": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 1
}
]
]
}
},
"active": false,
"settings": {},
"id": "3"
}