How to join two arrays by their properties?
Joining two arrays by a shared property is straightforward in fx because you write plain JavaScript. No need to learn a DSL like jq — just use familiar map, find, objects, and optional chaining.
Below are two common approaches using the same input. The first is simple and expressive; the second is faster for large arrays.
Example data
{
"posts": [
{ "id": 1, "title": "Hello", "author": 10 },
{ "id": 2, "title": "World", "author": 20 }
],
"users": [
{ "id": 10, "name": "Alice" },
{ "id": 20, "name": "Bob" }
]
}Using find
Use Array.prototype.find inside a map over the left-hand side array. This is essentially a left join: if the author is missing, you’ll get undefined (or whatever fallback you provide).
fx data.json 'x.posts.map(p => ({
title: p.title,
author: x.users.find(y => y.id == p.author)?.name
}))'Output:
[
{ "title": "Hello", "author": "Alice" },
{ "title": "World", "author": "Bob" }
]Notes:
- Optional chaining (
?.) avoids errors when there’s no match. - For small arrays this is perfectly fine. For very large arrays it’s O(n·m) and may be slower.
Build a lookup map
Precompute a dictionary from users keyed by id, then do a single pass over posts. This makes the join O(n + m).
fx data.json 'x => {
const names = {};
x.users.forEach(y => names[y.id] = y.name);
return x.posts.map(p => ({ ...p, author: names[p.author] }))
}'Output:
[
{ "id": 1, "title": "Hello", "author": "Alice" },
{ "id": 2, "title": "World", "author": "Bob" }
]One-to-many joins
Sometimes the right-hand side has multiple matches for a single left-hand row. In a one-to-many join you typically produce an array of matches per left item.
This mirrors the earlier find example, but uses filter to collect all matches:
fx data.json 'x.users.map(u => ({
id: u.id,
name: u.name,
posts: x.posts.filter(p => p.author == u.id)
}))'Output:
[
{
"id": 10,
"name": "Alice",
"posts": [
{ "id": 1, "title": "Hello", "author": 10 }
]
},
{
"id": 20,
"name": "Bob",
"posts": [
{ "id": 2, "title": "World", "author": 20 }
]
}
]