Skip to content

2024

Getting Started with CongraphDB

CongraphDB is an embedded graph database for Node.js applications. In this tutorial, we'll build a simple social network to learn the basics.

What We'll Build

A simple social network with: - Users - Friendships (relationships) - Friend recommendations

Installation

First, install CongraphDB:

npm install congraphdb

Creating the Database

const { Database } = require('congraphdb');

const db = new Database('./social-network.cgraph');
db.init();

const conn = db.createConnection();

Defining the Schema

// Create a User table
await conn.query(`
  CREATE NODE TABLE User(
    username STRING,
    display_name STRING,
    bio STRING,
    created_at INT64,
    PRIMARY KEY (username)
  )
`);

// Create a Knows relationship table
await conn.query(`
  CREATE REL TABLE Knows(FROM User TO User, since INT64)
`);

Adding Users

const users = [
  { username: 'alice', display_name: 'Alice', bio: 'Developer' },
  { username: 'bob', display_name: 'Bob', bio: 'Designer' },
  { username: 'charlie', display_name: 'Charlie', bio: 'PM' },
];

for (const user of users) {
  await conn.query(`
    CREATE (u:User {
      username: $username,
      display_name: $display_name,
      bio: $bio,
      created_at: $timestamp
    })
  `, { ...user, timestamp: Date.now() });
}

Creating Friendships

// Alice knows Bob
await conn.query(`
  MATCH (alice:User {username: 'alice'})
  MATCH (bob:User {username: 'bob'})
  CREATE (alice)-[:Knows {since: 2020}]->(bob)
`);

// Bob knows Charlie
await conn.query(`
  MATCH (bob:User {username: 'bob'})
  MATCH (charlie:User {username: 'charlie'})
  CREATE (bob)-[:Knows {since: 2021}]->(charlie)
`);

Querying the Graph

Find Alice's Friends

const result = await conn.query(`
  MATCH (u:User {username: 'alice'})-[:Knows]->(friend)
  RETURN friend.display_name
`);

for (const row of result.getAll()) {
  console.log(row['friend.display_name']);
}

Friend Recommendations

// Friends of friends I don't know yet
const result = await conn.query(`
  MATCH (me:User {username: 'alice'})-[:Knows]->(friend)-[:Knows]->(foaf:User)
  WHERE NOT (me)-[:Knows]->(foaf) AND me <> foaf
  RETURN foaf.display_name, COUNT(friend) AS mutual_friends
  ORDER BY mutual_friends DESC
`);

console.log('Friend recommendations:');
for (const row of result.getAll()) {
  console.log(`  ${row['foaf.display_name']} (${row.mutual_friends} mutual)`);
}

Cleanup

conn.close();
db.close();

Next Steps

Full Example

const { Database } = require('congraphdb');

async function main() {
  const db = new Database('./social-network.cgraph');
  db.init();
  const conn = db.createConnection();

  // Create schema
  await conn.query(`
    CREATE NODE TABLE User(
      username STRING,
      display_name STRING,
      bio STRING,
      PRIMARY KEY (username)
    )
  `);
  await conn.query(`
    CREATE REL TABLE Knows(FROM User TO User, since INT64)
  `);

  // Add users
  const users = [
    { username: 'alice', display_name: 'Alice', bio: 'Developer' },
    { username: 'bob', display_name: 'Bob', bio: 'Designer' },
    { username: 'charlie', display_name: 'Charlie', bio: 'PM' },
  ];

  for (const user of users) {
    await conn.query(`
      CREATE (u:User {username: $username, display_name: $display_name, bio: $bio})
    `, user);
  }

  // Add friendships
  await conn.query(`
    MATCH (alice:User {username: 'alice'})
    MATCH (bob:User {username: 'bob'})
    CREATE (alice)-[:Knows {since: 2020}]->(bob)
  `);

  // Query
  const result = await conn.query(`
    MATCH (u:User {username: 'alice'})-[:Knows]->(friend)
    RETURN friend.display_name
  `);

  console.log("Alice's friends:");
  for (const row of result.getAll()) {
    console.log(`- ${row['friend.display_name']}`);
  }

  db.close();
}

main().catch(console.error);

Happy graphing! :tada:

Vector Search Tutorial

CongraphDB includes built-in support for vector similarity search using HNSW (Hierarchical Navigable Small World) indexes. This tutorial shows you how to build a semantic search application.

Unlike keyword search, semantic search understands the meaning of text:

// Keyword search: "dog" ≠ "puppy"
// Semantic search: "dog" ≈ "puppy" (similar meanings)

Prerequisites

  • Node.js 20+
  • An embedding model (we'll use OpenAI in this example)

Setup

npm install congraphdb openai

Create a Document Store

const { Database } = require('congraphdb');
const OpenAI = require('openai');

const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });

async function getEmbedding(text) {
  const response = await openai.embeddings.create({
    model: 'text-embedding-3-small',
    input: text,
  });
  return response.data[0].embedding;
}

async function main() {
  const db = new Database('./doc-store.cgraph');
  db.init();
  const conn = db.createConnection();

  // Create schema with vector column
  await conn.query(`
    CREATE NODE TABLE Document(
      id STRING,
      title STRING,
      content STRING,
      embedding FLOAT_VECTOR[1536],
      PRIMARY KEY (id)
    )
  `);

  // Create HNSW index for fast search
  await conn.query(`
    CREATE HNSW INDEX ON Document(embedding, dim=1536, M=16)
  `);

Add Documents

  const documents = [
    {
      id: '1',
      title: 'Machine Learning Basics',
      content: 'Machine learning is a subset of artificial intelligence that enables systems to learn from data.',
    },
    {
      id: '2',
      title: 'Deep Learning Explained',
      content: 'Deep learning uses neural networks with multiple layers to learn patterns in data.',
    },
    {
      id: '3',
      title: 'Natural Language Processing',
      content: 'NLP enables computers to understand and generate human language using transformers.',
    },
    {
      id: '4',
      title: 'Computer Vision',
      content: 'Computer vision allows machines to interpret and understand visual information from images.',
    },
  ];

  for (const doc of documents) {
    const embedding = await getEmbedding(doc.content);
    await conn.query(`
      CREATE (d:Document {
        id: $id,
        title: $title,
        content: $content,
        embedding: $embedding
      })
    `, { ...doc, embedding });
  }
  // Search by meaning, not keywords
  const query = 'how do computers learn';
  const queryEmbedding = await getEmbedding(query);

  const result = await conn.query(`
    MATCH (d:Document)
    RETURN d.title, d.content, d.embedding <-> $query AS distance
    ORDER BY distance
    LIMIT 3
  `, { query: queryEmbedding });

  console.log(`Search results for: "${query}"`);
  console.log();
  for (const row of result.getAll()) {
    console.log(`${row['d.title']}`);
    console.log(`  ${row['d.content']}`);
    console.log(`  Distance: ${row.distance.toFixed(4)}`);
    console.log();
  }

  /*
  Output:
  Search results for: "how do computers learn"

  Machine Learning Basics
    Machine learning is a subset of artificial intelligence...
    Distance: 0.1523

  Deep Learning Explained
    Deep learning uses neural networks with multiple layers...
    Distance: 0.1234

  Natural Language Processing
    NLP enables computers to understand...
    Distance: 0.2134
  */

  db.close();
}

main().catch(console.error);

HNSW Parameters

Understanding HNSW parameters for your use case:

M (max connections)

// Default: 16
// Higher = more accurate, slower, more memory
CREATE HNSW INDEX ON Document(embedding, dim=1536, M=16)

// For small datasets (< 10K): M = 8-16
// For medium datasets (10K-100K): M = 16-32
// For large datasets (> 100K): M = 32-64

ef_construction (build-time)

// Default: 100
// Higher = better index quality, slower build
CREATE HNSW INDEX ON Document(embedding, dim=1536, M=16, ef_construction=100)

ef_runtime (search-time)

Controlled at query time via the LIMIT clause:

// More candidates = more accurate, slower
LIMIT 10  // ef_runtime ≈ 10 * 10 = 100

Performance Tips

  1. Batch insertions: Insert all documents before creating the index
  2. Dimension choice: Lower dimensions (128-384) are faster
  3. Monitor build time: Large indexes can take minutes to build

Complete Example

const { Database } = require('congraphdb');
const OpenAI = require('openai');

const openai = new OpenAI();

async function getEmbedding(text) {
  const response = await openai.embeddings.create({
    model: 'text-embedding-3-small',
    input: text,
  });
  return response.data[0].embedding;
}

async function search(query) {
  const db = new Database('./doc-store.cgraph');
  db.init();
  const conn = db.createConnection();

  const queryEmbedding = await getEmbedding(query);

  const result = await conn.query(`
    MATCH (d:Document)
    RETURN d.title, d.content, d.embedding <-> $query AS distance
    ORDER BY distance
    LIMIT 3
  `, { query: queryEmbedding });

  db.close();
  return result.getAll();
}

// Usage
search('neural network training').then(console.log);

Next Steps

Happy searching! :mag: