将 TypeScript 与 Neo4j 一起使用
作者:互联网
现在可以使用接口来定义 Cypher 查询返回的记录类型,从而在处理结果时提供类型检查和类型提示的额外好处。
一个工作的例子
例如,让我们从建议数据集中获取一个查询。假设我们想找到电影中出现过的所有演员的列表。
要找到它,我们需要创建一个新的驱动程序实例,打开一个新会话,然后使用该函数发送 Cypher 语句并等待结果。executeRead()
async function main() {
// Create a Driver Instance
const driver = neo4j.driver(
'neo4j://localhost:7687',
neo4j.auth.basic('neo4j', 'letmein!')
)
// Open a new Session
const session = driver.session()
try {
// Execute a Cypher statement in a Read Transaction
const res = await session.executeRead(tx => tx.run(`
MATCH (p:Person)-[r:ACTED_IN]->(m:Movie {title: $title})
RETURN p, r, m
`, { title: 'Pulp Fiction' }))
const people = res.records.map(row => row.get('p'))
console.log(people)
}
finally {
// Close the Session
await session.close()
}
}
足够简单,就像所有完美的开发人员一样,我们永远不会遇到以这种方式编写代码的任何问题。
另一方面,如果有人碰巧在行中输入拼写错误或尝试使用结果中未返回的值,则驱动程序将被写入以引发错误。res.records.map(row => row.get('p'))
.get()
假设该行更改为:
const people = res.records.map(row => row.get('something'))
由于结果中不存在,因此将抛出:something
Neo4jError
Neo4jError: This record has no field with key 'something',
available key are: [p,r,m].
当你运行应用程序时,你最终会发现这一点,但TypeScript的全部意义是在开发过程中识别这些错误。
添加类型检查
为了防止这种情况,我们现在可以使用接口来定义每条记录上可用的键。
在上述查询的情况下,我们有三个值:
p
- 带有标签的标签,其属性包括和Node
Person
name
born
r
- 具有属性的类型包括 - 字符串数组Relationship
ACTED_IN
roles
m
a 标签为 .Node
Movie
该库导出两个类型定义,以及 ,我们可以用来定义这些项。neo4j-driver
Node
Relationship
import neo4j, { Node, Relationship } from 'neo4j-driver'
这两个类都接受泛型来定义 的类型以及值上保存的属性。.identity
除非在创建驱动程序时设置了该选项,否则标识将是从 导出的类型实例。disableLosslessIntegers
Integer
neo4j-driver
人员值可以定义为 打字稿 。type
import { Integer } from 'neo4j-driver'
interface PersonProperties {
tmdbId: string;
name: string;
born: number; // Year of birth
}
type Person = Node<Integer, PersonProperties>
或者,对于更简洁的示例,可以直接在第二个泛型中定义属性:
type Movie = Node<Integer, {
tmdbId: string;
title: string;
rating: number;
}>
关系几乎相同,但改用类型。Relationship
type ActedIn = Relationship<Integer, {
roles: string[];
}>
这些类型可以在接口中组合,以表示结果中的每条记录:
interface PersonActedInMovie {
p: Person;
r: ActedIn;
m: Movie;
}
和 都接受接口,并将类型检查添加到任何后续处理中。可以更新上面的示例以将接口传递给方法调用。session.run()
tx.run()
PersonActedInMovie
tx.run()
// Execute a Cypher statement in a Read Transaction
const res = await session.executeRead(tx => tx.run<PersonActedInMovie>(`
MATCH (p:Person)-[r:ACTED_IN]->(m:Movie {title: $title})
RETURN p, r, m
`, { title: 'Pulp Fiction' }))
类型检查在操作
由于记录形状已定义,TypeScript 现在将在编写代码时对其进行验证并提供建议。
建议记录键
现在,在调用该方法时提供了建议。record.get()
建议属性
TypeScript 知道这是一个节点数组,可以在键入时建议界面中定义的属性。people
Person
检查属性键
如果节点或关系的属性中不存在键,TypeScript 将立即选取该键并抛出错误:
const names = people.map(
person => person.properties.foo
// Property 'foo' does not exist
// on type 'PersonProperties'
)
类型检查属性
TypeScript 现在还可以识别每个属性的类型,因此如果您尝试使用类型中未定义的值,TypeScript 将引发错误。