使用 Express 的 Javascript 代码演示
所有展示的代码均可作为一个使用 Express 的简单 Node.js 应用程序来运行。此应用程序使用了一个即开即用的演示数据库,其中包含 Goodreads 数据集,包含书籍 (Book) 和作者 (Author) 实体。

设置
安装 Neo4j 驱动程序和 Express
npm init -y
npm install neo4j-driver expressCode language: Shell Session (shell)
连接到数据库
由于此示例使用公共数据库,因此无需任何修改即可连接。
主应用程序 – app.js
const express = require('express');
const neo4j = require('neo4j-driver');
const app = express();
const PORT = 3000;
// Neo4j connection
// Create a driver instance to manage the connection to Neo4j
// The 'neo4j+s' protocol uses encrypted connections
const driver = neo4j.driver(
'neo4j+s://demo.neo4jlabs.com',
neo4j.auth.basic('goodreads', 'goodreads')
);
// GET /books - Get featured books from diverse authors
app.get('/books', async (req, res) => {
// Create a new session for this request
// Sessions are lightweight and should be created per request
const session = driver.session();
try {
// Execute a Cypher query to find books by specific authors
// The MATCH clause finds Book nodes connected to Author nodes
// The WHERE clause filters for specific author names
// COLLECT aggregates multiple authors into an array
const result = await session.run(
`MATCH (book:Book)<-[:AUTHORED]-(author:Author)
WHERE author.name IN ['Chimamanda Ngozi Adichie', 'James Baldwin',
'Toni Morrison', 'Maya Angelou', 'Gabriel García Márquez']
RETURN book.title AS title, collect(author.name) AS authors
LIMIT 10`
);
// Transform Neo4j records into JSON objects
// record.get() extracts values by their alias from the RETURN clause
const books = result.records.map(record => ({
title: record.get('title'),
authors: record.get('authors')
}));
res.json(books);
} catch (error) {
res.status(500).json({ error: error.message });
} finally {
// Always close the session to release resources
await session.close();
}
});
// GET /books/:title - Get book by title
app.get('/books/:title', async (req, res) => {
const session = driver.session();
try {
// Use parameterized queries to prevent Cypher injection
// The $title parameter is safely substituted by the driver
// OPTIONAL MATCH ensures we get the book even if it has no authors
const result = await session.run(
`MATCH (book:Book {title: $title})
OPTIONAL MATCH (book)<-[:AUTHORED]-(author:Author)
RETURN book.title AS title, book.isbn AS isbn,
collect(author.name) AS authors`,
{ title: req.params.title } // Parameters passed as second argument
);
// Check if any records were returned
if (result.records.length === 0) {
return res.status(404).json({ error: 'Book not found' });
}
// Extract data from the first (and only) record
const record = result.records[0];
res.json({
title: record.get('title'),
isbn: record.get('isbn'),
authors: record.get('authors')
});
} catch (error) {
res.status(500).json({ error: error.message });
} finally {
await session.close();
}
});
// GET /books/author/:name - Get books by author
app.get('/books/author/:name', async (req, res) => {
const session = driver.session();
try {
// Find all books written by a specific author
// The arrow in -[:AUTHORED]-> shows the relationship direction
// (author)-[:AUTHORED]->(book) means author wrote the book
const result = await session.run(
`MATCH (author:Author {name: $name})-[:AUTHORED]->(book:Book)
RETURN book.title AS title, book.isbn AS isbn
LIMIT 10`,
{ name: req.params.name }
);
// Map each record to a simplified book object
const books = result.records.map(record => ({
title: record.get('title'),
isbn: record.get('isbn')
}));
res.json(books);
} catch (error) {
res.status(500).json({ error: error.message });
} finally {
await session.close();
}
});
// Start the Express server
app.listen(PORT, () => {
console.log(`Server running on https://:${PORT}`);
console.log('\nTry these endpoints:');
console.log(' https://:3000/books');
console.log(' https://:3000/books/Americanah');
console.log(' https://:3000/books/author/Chimamanda%20Ngozi%20Adichie');
console.log(' https://:3000/books/author/James%20Baldwin');
});
// Cleanup on exit
// Gracefully close the driver connection when the process terminates
process.on('SIGINT', async () => {
await driver.close();
process.exit();
});Code language: JavaScript (javascript)
Express 框架通过简洁的端点定义简化了路由。每个端点都会创建一个会话 (session)、运行 Cypher 查询并返回 JSON 结果。这些查询特别重点展示了诸如 Chimamanda Ngozi Adichie、James Baldwin、Toni Morrison 和 Maya Angelou 等多元化作者。
关键概念解释
驱动程序与会话
- 驱动程序 (Driver):一个长期存在的对象,用于管理到 Neo4j 的连接池。每个应用程序只需创建一个。
- 会话 (Session):一个短期存在的对象,用于执行查询。每个请求/事务创建一个。
- 务必在 finally 块中关闭会话,以防止连接泄漏。
Cypher 查询模式
- MATCH:在图中查找模式
- OPTIONAL MATCH:类似于 MATCH,但如果模式不存在则返回 null(类似于 LEFT JOIN)
- WHERE:根据条件过滤结果
- RETURN:指定要返回的数据
- COLLECT:将值聚合为列表
参数化查询
始终使用参数(如 $title、$name)代替字符串拼接,以防止 Cypher 注入攻击
// Good - Safe from injection
session.run('MATCH (n:Node {name: $name})', { name: userInput })
// Bad - Vulnerable to injection
session.run(`MATCH (n:Node {name: '${userInput}'})`)Code language: JavaScript (javascript)
错误处理
try-catch-finally 模式确保:
- 错误被捕获并作为 HTTP 错误响应返回
- 即使发生错误,会话也会被关闭
- 资源得到妥善释放
运行并测试应用程序
运行服务器
node app.jsCode language: Shell Session (shell)
测试端点
# Get featured books from diverse authors
curl https://:3000/books
# Get a specific book
curl https://:3000/books/Americanah
curl "https://:3000/books/Half%20of%20a%20Yellow%20Sun"
# Get books by Chimamanda Ngozi Adichie
curl "https://:3000/books/author/Chimamanda%20Ngozi%20Adichie"
# Get books by James Baldwin
curl "https://:3000/books/author/James%20Baldwin"
# Get books by Toni Morrison
curl "https://:3000/books/author/Toni%20Morrison"Code language: Shell Session (shell)
或使用 HTTPie
http :3000/books
http ":3000/books/Americanah"
http ":3000/books/author/Chimamanda Ngozi Adichie"
http ":3000/books/author/James Baldwin"Code language: Shell Session (shell)
响应示例
// GET /books
[
{
"title": "Americanah",
"authors": ["Chimamanda Ngozi Adichie"]
},
{
"title": "Half of a Yellow Sun",
"authors": ["Chimamanda Ngozi Adichie"]
},
{
"title": "The Fire Next Time",
"authors": ["James Baldwin"]
}
]
// GET /books/author/Chimamanda%20Ngozi%20Adichie
[
{
"title": "Americanah",
"isbn": "0307455920"
},
{
"title": "Half of a Yellow Sun",
"isbn": "1400044162"
},
{
"title": "Purple Hibiscus",
"isbn": "1616202416"
}
]Code language: JavaScript (javascript)


