UltipaDocs
Try Playground
  • Introduction
    • Quick Start
    • Configuration
    • Connection and Session
    • Executing Queries
    • Graph Management
    • Transactions
    • Data Operations
    • Bulk Import
    • Data Export
    • Health and Administration
    • Response Processing
    • Data Types
    • Error Handling
    • Quick Start
    • Configuration
    • Connection and Session
    • Executing Queries
    • Graph Management
    • Transactions
    • Data Operations
    • Bulk Import
    • Data Export
    • Health and Administration
    • Response Processing
    • Data Types
    • Error Handling
    • Quick Start
    • Configuration
    • Connection and Session
    • Executing Queries
    • Graph Management
    • Transactions
    • Data Operations
    • Bulk Import
    • Data Export
    • Health and Administration
    • Response Processing
    • Data Types
    • Error Handling
    • Quick Start
    • Configuration
    • Connection and Session
    • Executing Queries
    • Graph Management
    • Transactions
    • Data Operations
    • Bulk Import
    • Data Export
    • Health and Administration
    • Response Processing
    • Data Types
    • Error Handling
  1. Docs
  2. /
  3. Ultipa Drivers
  4. /
  5. Node.js

Response Processing

The GQLDB Node.js driver provides the Response and Row classes for working with query results. This guide covers how to extract and convert data from query responses.

Response Class

The gql() method returns a Response object containing query results:

TypeScript
import { GqldbClient, Response } from 'gqldb-nodejs';

async function queryExample(client: GqldbClient) {
  const response: Response = await client.gql('MATCH (n:User) RETURN n.name, n.age');

  console.log('Columns:', response.columns);     // ['n.name', 'n.age']
  console.log('Row count:', response.rowCount);  // Number of rows
  console.log('Has more:', response.hasMore);    // Pagination indicator
  console.log('Warnings:', response.warnings);   // Any query warnings
  console.log('Rows affected:', response.rowsAffected);  // For write operations
}

Response Properties

PropertyTypeDescription
columnsstring[]Column names from the query
rowsRow[]Array of result rows
rowCountnumberTotal number of rows
hasMorebooleanWhether more results are available
warningsstring[]Query warnings
rowsAffectednumberRows affected by write operations
lengthnumberSame as rows.length

Row Class

Each row contains values that can be accessed by index:

TypeScript
const response = await client.gql('MATCH (n:User) RETURN n.name, n.age, n.active');

for (const row of response.rows) {
  // Access by index
  const name = row.get(0);    // First column
  const age = row.get(1);     // Second column
  const active = row.get(2);  // Third column

  // Typed accessors
  const nameStr = row.getString(0);    // Returns string
  const ageNum = row.getNumber(1);     // Returns number
  const activeBool = row.getBoolean(2); // Returns boolean

  console.log(`${nameStr}, age ${ageNum}, active: ${activeBool}`);
}

Row Methods

MethodReturn TypeDescription
get(index)anyGet value at index
getString(index)stringGet value as string
getNumber(index)numberGet value as number
getBoolean(index)booleanGet value as boolean
getType(index)PropertyTypeGet the property type at index

Iterating Results

Using for...of

TypeScript
const response = await client.gql('MATCH (n) RETURN n');

// Response implements Symbol.iterator
for (const row of response) {
  console.log(row.get(0));
}

Using forEach

TypeScript
response.forEach((row, index) => {
  console.log(`Row ${index}:`, row.get(0));
});

Using map

TypeScript
const names = response.map(row => row.getString(0));
console.log('Names:', names);

Quick Access Methods

First and Last Row

TypeScript
const first = response.first();  // First row or undefined
const last = response.last();    // Last row or undefined

if (first) {
  console.log('First result:', first.get(0));
}

Check if Empty

TypeScript
if (response.isEmpty()) {
  console.log('No results found');
}

Single Value

For queries that return a single row with a single column:

TypeScript
const countResponse = await client.gql('MATCH (n) RETURN count(n)');
const count = countResponse.singleValue();  // Returns the single value

// Typed single value accessors
const countNum = countResponse.singleNumber();  // As number
const countStr = countResponse.singleString();  // As string

Converting to Objects

toObjects()

Convert rows to an array of plain objects:

TypeScript
const response = await client.gql('MATCH (u:User) RETURN u.name AS name, u.age AS age');
const users = response.toObjects();

// Result: [{ name: 'Alice', age: 30 }, { name: 'Bob', age: 25 }]
for (const user of users) {
  console.log(`${user.name} is ${user.age} years old`);
}

toJSON()

Convert to JSON string:

TypeScript
const json = response.toJSON();
console.log(json);
// '[{"name":"Alice","age":30},{"name":"Bob","age":25}]'

Get Value by Column Name

TypeScript
const response = await client.gql('MATCH (u:User) RETURN u.name AS name, u.age AS age');

for (const row of response.rows) {
  const name = response.getByName(row, 'name');
  const age = response.getByName(row, 'age');
  console.log(`${name}: ${age}`);
}

Extracting Graph Elements

asNodes()

Extract nodes from the response:

TypeScript
import { Node, NodeResult, Schema } from 'gqldb-nodejs';

const response = await client.gql('MATCH (u:User) RETURN u');
const result: NodeResult = response.asNodes();

// Access nodes
for (const node of result.nodes) {
  console.log('ID:', node.id);
  console.log('Labels:', node.labels);
  console.log('Properties:', node.properties);
}

// Access inferred schemas
for (const [label, schema] of result.schemas) {
  console.log(`Schema for ${label}:`, schema);
}

Node Interface

TypeScript
interface Node {
  id: string;
  labels: string[];
  properties: Record<string, any>;
}

interface NodeResult {
  nodes: Node[];
  schemas: Map<string, Schema>;
}

asEdges()

Extract edges from the response:

TypeScript
import { Edge, EdgeResult } from 'gqldb-nodejs';

const response = await client.gql('MATCH ()-[e:Follows]->() RETURN e');
const result: EdgeResult = response.asEdges();

for (const edge of result.edges) {
  console.log('ID:', edge.id);
  console.log('Label:', edge.label);
  console.log('From:', edge.fromNodeId);
  console.log('To:', edge.toNodeId);
  console.log('Properties:', edge.properties);
}

Edge Interface

TypeScript
interface Edge {
  id: string;
  label: string;
  fromNodeId: string;
  toNodeId: string;
  properties: Record<string, any>;
}

interface EdgeResult {
  edges: Edge[];
  schemas: Map<string, Schema>;
}

asPaths()

Extract paths from the response:

TypeScript
import { Path } from 'gqldb-nodejs';

const response = await client.gql('MATCH p = (a)-[*1..3]->(b) RETURN p LIMIT 10');
const paths: Path[] = response.asPaths();

for (const path of paths) {
  console.log('Path nodes:', path.nodes.length);
  console.log('Path edges:', path.edges.length);

  // Print path
  for (let i = 0; i < path.nodes.length; i++) {
    console.log(`  Node: ${path.nodes[i].id}`);
    if (i < path.edges.length) {
      console.log(`    -[${path.edges[i].label}]->`);
    }
  }
}

Path Interface

TypeScript
interface Path {
  nodes: Node[];
  edges: Edge[];
}

Table Format

asTable()

Get the response as a generic table:

TypeScript
import { Table, Header } from 'gqldb-nodejs';

const response = await client.gql('MATCH (u:User) RETURN u.name, u.age');
const table: Table = response.asTable();

console.log('Headers:', table.headers.map(h => h.name));
console.log('Rows:', table.rows);

Table Interface

TypeScript
interface Table {
  name: string;
  headers: Header[];
  rows: any[][];
}

interface Header {
  name: string;
  type: PropertyType;
}

Attribute Extraction

asAttr()

Extract values from a specific column:

TypeScript
import { Attr } from 'gqldb-nodejs';

const response = await client.gql('MATCH (u:User) RETURN u.age AS age');
const ageAttr: Attr = response.asAttr('age');

console.log('Column name:', ageAttr.name);
console.log('Type:', ageAttr.type);
console.log('Values:', ageAttr.values);

// Calculate statistics
const ages = ageAttr.values as number[];
const avgAge = ages.reduce((a, b) => a + b, 0) / ages.length;
console.log('Average age:', avgAge);

Attr Interface

TypeScript
interface Attr {
  name: string;
  type: PropertyType;
  values: any[];
}

Complete Example

TypeScript
import { GqldbClient, createConfig } from 'gqldb-nodejs';

async function main() {
  const client = new GqldbClient(createConfig({
    hosts: ['192.168.1.100:9000'],
    defaultGraph: 'socialNetwork'
  }));

  try {
    await client.login('admin', 'password');

    // Query nodes
    console.log('=== Query Nodes ===');
    const nodeResponse = await client.gql('MATCH (u:User) RETURN u LIMIT 5');
    const { nodes } = nodeResponse.asNodes();
    for (const node of nodes) {
      console.log(`User ${node.id}: ${node.properties.name}`);
    }

    // Query with multiple columns
    console.log('\n=== Query Columns ===');
    const colResponse = await client.gql(
      'MATCH (u:User) RETURN u.name AS name, u.age AS age ORDER BY u.age DESC LIMIT 3'
    );
    const users = colResponse.toObjects();
    console.log('Top 3 oldest users:', users);

    // Query paths
    console.log('\n=== Query Paths ===');
    const pathResponse = await client.gql(
      'MATCH p = (a:User)-[:Follows*1..2]->(b:User) RETURN p LIMIT 3'
    );
    const paths = pathResponse.asPaths();
    for (const path of paths) {
      const route = path.nodes.map(n => n.properties.name || n.id).join(' -> ');
      console.log(`Path: ${route}`);
    }

    // Aggregate query
    console.log('\n=== Aggregate Query ===');
    const countResponse = await client.gql('MATCH (n) RETURN count(n)');
    console.log('Total nodes:', countResponse.singleNumber());

    // Extract attribute values
    console.log('\n=== Attribute Extraction ===');
    const ageResponse = await client.gql('MATCH (u:User) RETURN u.age AS age');
    const ages = ageResponse.asAttr('age');
    const numericAges = ages.values.filter(a => typeof a === 'number') as number[];
    if (numericAges.length > 0) {
      console.log('Ages:', numericAges);
      console.log('Min age:', Math.min(...numericAges));
      console.log('Max age:', Math.max(...numericAges));
    }

  } finally {
    await client.close();
  }
}

main().catch(console.error);