Agent skill

Neo4j

Use Neo4j for graph data modeling, relationship traversal, and complex connected data queries.

Stars 10
Forks 1

Install this agent skill to your Project

npx add-skill https://github.com/hivellm/rulebook/tree/main/templates/skills/services/neo4j

SKILL.md

Neo4j Graph Database Instructions

CRITICAL: Use Neo4j for graph data modeling, relationship traversal, and complex connected data queries.

Core Features

Connection

typescript
// Using neo4j-driver
import neo4j from 'neo4j-driver'

const driver = neo4j.driver(
  process.env.NEO4J_URI || 'bolt://localhost:7687',
  neo4j.auth.basic(
    process.env.NEO4J_USER || 'neo4j',
    process.env.NEO4J_PASSWORD || 'password'
  ),
  {
    maxConnectionLifetime: 3 * 60 * 60 * 1000, // 3 hours
    maxConnectionPoolSize: 50,
    connectionAcquisitionTimeout: 2 * 60 * 1000, // 2 minutes
  }
)

const session = driver.session()

Basic Operations

typescript
// Create node
const result = await session.run(
  'CREATE (u:User {id: $id, name: $name, email: $email}) RETURN u',
  { id: '1', name: 'John Doe', email: 'john@example.com' }
)

// Create relationship
await session.run(
  'MATCH (u:User {id: $userId}), (p:Post {id: $postId}) CREATE (u)-[:CREATED]->(p)',
  { userId: '1', postId: '1' }
)

// Find nodes
const result = await session.run(
  'MATCH (u:User {email: $email}) RETURN u',
  { email: 'john@example.com' }
)
const user = result.records[0]?.get('u')

// Update node
await session.run(
  'MATCH (u:User {id: $id}) SET u.name = $name, u.updatedAt = $updatedAt',
  { id: '1', name: 'Jane Doe', updatedAt: new Date().toISOString() }
)

// Delete node and relationships
await session.run(
  'MATCH (u:User {id: $id}) DETACH DELETE u',
  { id: '1' }
)

Advanced Queries

typescript
// Find relationships
const result = await session.run(`
  MATCH (u:User)-[r:FOLLOWS]->(f:User)
  WHERE u.id = $userId
  RETURN f, r.createdAt
  ORDER BY r.createdAt DESC
  LIMIT 10
`, { userId: '1' })

// Shortest path
const result = await session.run(`
  MATCH path = shortestPath(
    (start:User {id: $startId})-[*]-(end:User {id: $endId})
  )
  RETURN path, length(path) as distance
`, { startId: '1', endId: '2' })

// Pattern matching
const result = await session.run(`
  MATCH (u:User)-[:CREATED]->(p:Post)-[:TAGGED_WITH]->(t:Tag)
  WHERE t.name = $tagName
  RETURN u, count(p) as postCount
  ORDER BY postCount DESC
`, { tagName: 'javascript' })

// Aggregations
const result = await session.run(`
  MATCH (u:User)-[:FOLLOWS]->(f:User)
  RETURN u.id, count(f) as followerCount
  ORDER BY followerCount DESC
  LIMIT 10
`)

Common Patterns

User Recommendations

typescript
async function getRecommendedUsers(userId: string) {
  const result = await session.run(`
    MATCH (u:User {id: $userId})-[:FOLLOWS]->(f:User)-[:FOLLOWS]->(recommended:User)
    WHERE NOT (u)-[:FOLLOWS]->(recommended) AND u <> recommended
    RETURN recommended, count(recommended) as mutualFollowers
    ORDER BY mutualFollowers DESC
    LIMIT 10
  `, { userId })
  
  return result.records.map(record => ({
    user: record.get('recommended').properties,
    score: record.get('mutualFollowers').toNumber(),
  }))
}

Graph Traversal

typescript
async function findConnections(userId: string, depth: number) {
  const result = await session.run(`
    MATCH path = (start:User {id: $userId})-[*1..${depth}]-(connected:User)
    RETURN connected, length(path) as distance
    ORDER BY distance
  `, { userId })
  
  return result.records.map(record => ({
    user: record.get('connected').properties,
    distance: record.get('distance').toNumber(),
  }))
}

Transaction

typescript
const session = driver.session()
const tx = session.beginTransaction()

try {
  await tx.run('CREATE (u:User {id: $id, name: $name})', { id: '1', name: 'John' })
  await tx.run('CREATE (p:Post {id: $id, title: $title})', { id: '1', title: 'Post 1' })
  await tx.run(
    'MATCH (u:User {id: $userId}), (p:Post {id: $postId}) CREATE (u)-[:CREATED]->(p)',
    { userId: '1', postId: '1' }
  )
  await tx.commit()
} catch (error) {
  await tx.rollback()
  throw error
} finally {
  await session.close()
}

Best Practices

DO:

  • Use parameterized queries ($param)
  • Create indexes on frequently queried properties
  • Use appropriate relationship types
  • Batch operations when possible
  • Close sessions after use
  • Use transactions for multi-step operations
  • Monitor query performance
  • Use appropriate data types
  • Implement connection pooling
  • Use labels effectively

DON'T:

  • Use string concatenation for queries (injection risk)
  • Create too many relationships per node
  • Skip error handling
  • Ignore query performance
  • Hardcode connection strings
  • Store large properties (use external storage)
  • Skip indexes on lookup properties
  • Ignore transaction boundaries
  • Use synchronous operations
  • Store sensitive data without encryption

Configuration

Environment Variables

bash
NEO4J_URI=bolt://localhost:7687
NEO4J_URI=neo4j+s://cluster.example.com:7687  # SSL
NEO4J_USER=neo4j
NEO4J_PASSWORD=securepassword

Docker Compose

yaml
services:
  neo4j:
    image: neo4j:5
    ports:
      - "7474:7474"  # HTTP
      - "7687:7687"  # Bolt
    environment:
      NEO4J_AUTH: neo4j/securepassword
      NEO4J_PLUGINS: '["apoc"]'
    volumes:
      - neo4j_data:/data
      - neo4j_logs:/logs
    healthcheck:
      test: ["CMD", "cypher-shell", "-u", "neo4j", "-p", "securepassword", "RETURN 1"]
      interval: 10s
      timeout: 5s
      retries: 5

volumes:
  neo4j_data:
  neo4j_logs:

Integration with Development

Testing

typescript
// Use test database
const testDriver = neo4j.driver('bolt://localhost:7688', neo4j.auth.basic('neo4j', 'test'))

// Clean up after tests
afterEach(async () => {
  const session = testDriver.session()
  await session.run('MATCH (n) DETACH DELETE n')
  await session.close()
})

Health Checks

typescript
async function checkNeo4jHealth(): Promise<boolean> {
  try {
    const session = driver.session()
    const result = await session.run('RETURN 1 as health')
    await session.close()
    return result.records.length > 0
  } catch {
    return false
  }
}

Didn't find tool you were looking for?

Be as detailed as possible for better results