Skip to main content

Bulk Lookup by Name List

When you have a batch of names and need their IDs (e.g. a CSV column says "Backed by: Stability AI, Anthropic, OpenAI" and you need to convert those names to entity IDs to publish a relation), don't loop with N round-trips. Use a single bulk query.

Query

query BulkLookup($names: [String!]!) {
entities(
first: 100
filter: { name: { in: $names } }
) {
id
name
types { id name }
}
}
{ "names": ["OpenAI", "Anthropic", "Stability AI"] }

Response

{
"data": {
"entities": [
{ "id": "019d74a2f7ea4ffd9d3dfc07f25217df", "name": "OpenAI", "types": [{ "id": "e059a29e6f6b437bbc15c7983d078c0d", "name": "Company" }] },
{ "id": "09487a5ae4014091ba4310bd3d734bc5", "name": "OpenAI", "types": [{ "id": "e059a29e6f6b437bbc15c7983d078c0d", "name": "Company" }] },
{ "id": "150eb37e739346abb1021f3c291e54cc", "name": "Anthropic", "types": [{ "id": "e059a29e6f6b437bbc15c7983d078c0d", "name": "Company" }] }
]
}
}
Loading interactive query runner…

Building the lookup table client-side

const data = await gql(query, { names: ["OpenAI", "Anthropic", "Stability AI"] });

// One name can map to MULTIPLE entities — disambiguate by type and/or space
const byName = new Map<string, Array<{ id: string; types: string[] }>>();
for (const e of data.entities) {
const list = byName.get(e.name) ?? [];
list.push({ id: e.id, types: e.types.map((t) => t.id) });
byName.set(e.name, list);
}

// Resolve a name → ID, preferring entities of a specific type
function resolveName(name: string, expectedTypeId?: string): string | null {
const matches = byName.get(name);
if (!matches || matches.length === 0) return null;
if (expectedTypeId) {
const typed = matches.find((m) => m.types.includes(expectedTypeId));
if (typed) return typed.id;
}
return matches[0].id; // fallback: first match
}

Scoping bulk lookup to a space

query BulkLookupInSpace($names: [String!]!, $spaceId: UUID!) {
entities(
first: 100
filter: {
name: { in: $names }
spaceIds: { anyEqualTo: $spaceId }
}
) {
id
name
}
}

This is what you usually want during ingestion — "do any of these names already exist in my target space?".

Loading interactive query runner…

Notes

  • first: 100 is the default cap — pass a larger first if you batch more than 100 names at once. The API doesn't enforce a hard limit but very large name lists may slow down the query.
  • Duplicate names are common: the API doesn't dedup names, so for popular names like "OpenAI" you'll get multiple results. Always inspect types and spaceIds to pick the right one.
  • Case-sensitive: name: { in: [...] } is exact-match. For case-insensitive bulk lookup, you have to go one-by-one with name: { equalToInsensitive: ... }. Best to normalize your name list to the casing actually stored in the graph.
  • Versus a loop of single lookups: bulk is one HTTP round-trip vs N round-trips. For 50 names that's the difference between ~200ms and ~5s.