Flutter图数据库操作插件dgraph的使用
Flutter图数据库操作插件dgraph的使用
dgraph
Dgraph
Dart客户端通过gRPC
与服务器通信。
在使用此客户端之前,我们强烈建议您访问游dgraph.io和文档dgraph.io以了解如何运行和使用Dgraph。
目录
支持的版本
根据您连接的Dgraph版本,您将需要使用不同的客户端版本。
Dgraph版本 | dgraph客户端版本 |
---|---|
dgraph 1.0.X | dgraph客户端 0.5.0 |
dgraph 1.1.X | dgraph客户端 1.1.X |
注意:从dgraph客户端v0.5.0到v1.1.X最重要的API更改在于函数Txn.Mutate
。该函数在v0.5.0返回一个api.Assigned
值,但在v1.1.X返回一个api.Response
值。
使用客户端
创建客户端
dgraphClient
对象可以通过传递一个或多个api.DgraphApi
客户端作为变参来初始化。连接到同一集群中的多个Dgraph服务器可以更好地分配工作负载。
以下代码片段仅展示了一个连接:
DgraphRpcClient rpcClient =
DgraphRpcClient("localhost", 9080, const ChannelCredentials.insecure());
Dgraph dgraphClient = dgraph.NewDgraphClient(api.DgraphApi(rpcClient));
修改数据库
要设置模式,创建一个api.Operation
实例并使用Alter
端点。
api.Operation operation = api.Operation();
operation.schema = """
name: string @index(exact) .
""";
await dgraphClient.Alter(clientContext, operation);
Operation
包含其他字段,包括dropAttr
和dropAll
。dropAll
如果您希望丢弃所有数据,并从一个干净的起点开始,而不关闭实例,这很有用。dropAttr
用于删除与谓词相关的所有数据。
创建事务
要创建事务,调用dgraphClient.NewTxn()
,这会返回一个Txn
对象。此操作不会产生网络开销。
最好在初始化后在finally块中调用txn.Discard()
。在调用txn.Commit()
之后调用txn.Discard()
是一个空操作,您可以多次调用txn.Discard()
而不会产生额外的副作用。
Txn txn;
ClientContext clientContext = ClientContext();
try {
txn = dgraphClient.NewTxn();
// 执行一些查询和变异。
// 提交事务。
} finally {
txn.Discard(clientContext);
}
只读事务可以通过调用dgraphClient.NewReadOnlyTxn()
创建。只读事务有助于提高读取速度,因为它们可以绕过通常的共识协议。只读事务不能包含变异,并且尝试调用txn.Commit()
将导致错误。调用txn.Discard()
将是一个空操作。
运行变异
txn.Mutate(clientContext, mutation)
运行变异。它接受一个ClientContext
和一个api.Mutation
对象。您可以使用JSON或RDF N-Quad格式设置数据。
为了使用JSON,使用setJson和deleteJson字段,它们接受一个表示要添加或删除的节点的编码字符串(要么是JSON映射,要么是列表)。为了使用RDF,使用setNquads和delNquads字段,它们接受一个表示有效RDF三元组(每行一个)的字符串,用于添加或删除。
定义一个Map来表示一个人,并将其转换为与Mutation
对象一起使用。
Map<String, dynamic> p = {
"uid": "_:alice",
"name": "Alice",
};
List<int> pb = utf8.encode(json.encode(p));
api.Mutation mutation = api.Mutation();
mutation.setJson = pb;
api.Request request = api.Request();
request.mutations.add(mutation);
api.Response response = await txn.Mutate(clientContext, request);
print("Response: ${response.uids}");
// {alice: 0x5}
有时,您只想提交变异,而不进行进一步的查询。在这种情况下,您可以使用mutation.commitNow = true
来指示必须立即提交变异。
运行查询
您可以调用txn.Query(clientContext, query)
来运行查询。您需要传递一个GraphQL±查询字符串。如果您想传递任何变量,可以在查询中设置,可以调用txn.QueryWithVars(clientContext, query, vars)
,第三个参数为变量映射。
让我们运行以下带有变量$a
的查询:
String query = """
query all(\$a: string) {
all(func: eq(name, \$a)) {
name
}
}
""";
api.Response response =
await txn.QueryWithVars(clientContext, query, {"\$a": "Alice"});
print("Response: ${utf8.decode(response.json)}");
// {"all":[{"name":"Alice"}]}
您也可以使用txn.Do
函数来运行查询。
request = api.Request();
request.query = query;
request.vars.addAll({"\$a": "Alice"});
response = await txn.Do(clientContext, request);
print("Response: ${utf8.decode(response.json)}");
// {"all":[{"name":"Alice"}]}
当运行针对谓词name
的模式查询时,模式响应在api.Response
的json
字段中找到,如下所示:
String query = """
schema(pred: [name]) {
type
index
reverse
tokenizer
list
count
upsert
lang
}
""";
api.Response response = await txn.Query(clientContext, query);
print("Response: ${utf8.decode(response.json)}");
// {"schema":[{"predicate":"name","type":"string","index":true,"tokenizer":["exact"]}]}
提交事务
事务可以通过txn.Commit(clientContext)
方法提交。如果您的事务仅由对txn.Query
或txn.QueryWithVars
的调用组成,并且没有对txn.Mutate
的调用,则没有必要调用txn.Commit
。
如果其他并发运行的事务修改了此事务中修改的数据,则将返回错误。用户必须重试失败的事务。
Txn txn;
ClientContext clientContext = ClientContext();
try {
txn = dgraphClient.NewTxn();
// 执行一些查询和变异。
await txn.Commit(clientContext);
} catch (e) {
// 重试或处理错误
}
开发
运行测试
确保您安装了dgraph
后再运行测试。此脚本将运行单元测试。
pub run test --concurrency=1
更新protobuf
要更新protobuf,请执行以下命令:
bash lib/protos/api/regenerate-proto.sh
示例代码
import 'package:dgraph/api.dart';
import 'package:dgraph/dgraph.dart';
import 'package:dgraph/protos/api/api.pb.dart' as api;
import 'package:dgraph/txn.dart';
import 'package:grpc/grpc.dart';
import 'package:protobuf/protobuf.dart';
import 'dart:convert';
void main(List<String> arguments) async {
// 创建客户端
DgraphRpcClient rpcClient =
DgraphRpcClient("localhost", 9080, const ChannelCredentials.insecure());
Dgraph dgraphClient = dgraph.NewDgraphClient(api.DgraphApi(rpcClient));
Txn? txn;
ClientContext clientContext = ClientContext();
try {
// 修改数据库
api.Operation operation = api.Operation();
operation.schema = """
name: string @index(exact) .
""";
await dgraphClient.Alter(clientContext, operation);
txn = dgraphClient.NewTxn();
String query = """
schema(pred: [name]) {
type
index
reverse
tokenizer
list
count
upsert
lang
}
""";
api.Response response = await txn.Query(clientContext, query);
print("Response: ${utf8.decode(response.json)}");
txn.Discard(clientContext);
// 创建事务
txn = dgraphClient.NewTxn();
// 运行变异
Map<String, dynamic> p = {
"uid": "_:alice",
"name": "Alice",
"age": 18,
};
List<int> pb = utf8.encode(json.encode(p));
api.Mutation mutation = api.Mutation();
mutation.setJson = pb;
api.Request request = api.Request();
request.mutations.add(mutation);
response =
await (txn.Mutate(clientContext, request) as Future<api.Response>);
print("Response: ${response.uids}");
// 运行查询
query = """
query all(\$a: string) {
all(func: eq(name, \$a)) {
name
age
}
}
""";
response = await txn.QueryWithVars(clientContext, query, {"\$a": "Alice"});
print("Response: ${utf8.decode(response.json)}");
// 提交事务
await txn.Commit(clientContext);
// 修改数据库
operation = api.Operation();
operation.dropAttr = "age";
await dgraphClient.Alter(clientContext, operation);
// 创建另一个事务
txn = dgraphClient.NewReadOnlyTxn();
// 再次运行相同的查询
response = await txn.QueryWithVars(clientContext, query, {"\$a": "Alice"});
print("Response: ${utf8.decode(response.json)}");
// 再次运行相同的查询,但现在使用txn.Do
request = api.Request();
request.query = query;
request.vars.addAll({"\$a": "Alice"});
response = await (txn.Do(clientContext, request) as Future<api.Response>);
print("Response: ${utf8.decode(response.json)}");
// 结束事务但不提交
await txn.Discard(clientContext);
// 修改数据库
operation = api.Operation();
operation.dropAll = true;
await dgraphClient.Alter(clientContext, operation);
} catch (e) {
print("Error: $e");
} finally {
if (txn != null) {
await txn.Discard(clientContext);
}
}
}
更多关于Flutter图数据库操作插件dgraph的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter图数据库操作插件dgraph的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter中使用Dgraph图数据库操作插件的一个基本示例。由于Flutter本身没有直接的Dgraph插件,我们通常需要通过HTTP请求与Dgraph的GraphQL API进行交互。因此,我们会使用Dart的HTTP客户端库如http
或dio
来发送请求。
在这个示例中,我们将使用dio
库,因为它提供了更丰富的功能和更好的错误处理。
1. 添加依赖
首先,在你的pubspec.yaml
文件中添加dio
依赖:
dependencies:
flutter:
sdk: flutter
dio: ^4.0.0 # 请检查最新版本号
然后运行flutter pub get
来安装依赖。
2. 创建Dgraph服务类
接下来,我们创建一个服务类来处理与Dgraph的交互。
import 'package:dio/dio.dart';
class DgraphService {
final Dio dio;
DgraphService(String baseUrl) {
dio = Dio(
BaseOptions(
baseUrl: baseUrl,
connectTimeout: 5000,
receiveTimeout: 3000,
)
);
}
// 发送GraphQL查询
Future<Map<String, dynamic>> query(String query) async {
try {
Response response = await dio.post(
"/query",
data: {'query': query},
);
return response.data;
} catch (e) {
print("Error: $e");
rethrow;
}
}
// 发送GraphQL变更(mutation)
Future<Map<String, dynamic>> mutate(String mutation) async {
try {
Response response = await dio.post(
"/mutate",
data: {'mutations': mutation.split('\n').map((e) => '{"set": $e}').toList()},
options: Options(
contentType: Headers.formUrlEncodedContentType,
),
);
return response.data;
} catch (e) {
print("Error: $e");
rethrow;
}
}
}
3. 使用Dgraph服务类
现在,我们可以在Flutter应用中使用这个服务类来与Dgraph交互。
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:your_app/dgraph_service.dart'; // 假设你的文件名为dgraph_service.dart
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final DgraphService dgraphService = DgraphService("http://localhost:8080"); // Dgraph服务器地址
String responseData = "";
@override
void initState() {
super.initState();
_executeQuery();
}
Future<void> _executeQuery() async {
String query = """
{
all(func: eq(name, "Alice")) {
uid
name
}
}
""";
try {
Map<String, dynamic> result = await dgraphService.query(query);
setState(() {
responseData = result.toString();
});
} catch (e) {
print("Failed to execute query: $e");
}
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Flutter Dgraph Example'),
),
body: Center(
child: Text(responseData),
),
),
);
}
}
4. 运行应用
确保你的Dgraph服务器正在运行,并且可以通过http://localhost:8080
访问。然后运行你的Flutter应用,你应该能够看到从Dgraph获取的数据。
注意
- 安全性:在实际应用中,不要在生产环境中硬编码敏感信息(如服务器地址和凭证)。使用环境变量或安全存储机制。
- 错误处理:上面的示例中简单地打印了错误。在实际应用中,你可能需要更详细的错误处理和用户反馈。
- 性能:对于大型数据集,可能需要优化查询和变更操作。
这个示例提供了一个基本的框架,你可以根据需要进行扩展和修改。