2

抱歉,如果这个问题很明显,但我似乎找不到足够的文档。我可能缺乏关于宁静方法的知识。如何存储具有关系的记录?

我有一个地方。我想存储用户发布到这个地方的帖子。所以一个地方可以有很多帖子。一个帖子属于一个地方。

我正在使用 Aqueduct 3.0 预发布版。

我有以下型号:

地点.dart

class Place extends ManagedObject<_Place> implements _Place {}

class _Place {
  @primaryKey
  int id;

  @Column(unique: true)
  String name;

  ManagedSet<Post> posts;
}

post.dart

import 'package:places_api/model/place.dart';
import 'package:places_api/places_api.dart';

class Post extends ManagedObject<_Post> implements _Post {}

class _Post {
  @primaryKey
  int id;

  @Column()
  String text;

  @Relate(#posts)
  Place place;
}

我尝试保存帖子,但只能存储地点对象,而不是地点 ID。显然,下面的 post 查询不起作用,因为只有 values.place 对象,而不是 values.place_id 属性。是否打算加载该地点,然后将所有帖子存储到该地点?

同样没有关系,我无法存储 place_id,因为 Aqueduct 似乎将 _ 视为特殊的东西。我不能使用带有下划线的数据库属性吗?

有什么例子可以解释这一点吗?

  @Operation.post()
  Future<Response> createPost() async {
    final body = request.body.asMap();
    final query = new Query<Post>(context)
      ..values.place_id = body['place_id']
      ..values.text = body['text'];

    final insertedPost = await query.insert();

    return new Response.ok(insertedPost);
  }

目前我将以下正文作为 POST 发送:

{
    "place_id": 1,
    "text": "My post here"
}

到以下网址:http://localhost:8888/posts

发送这样的东西会更好吗?

{
    "text": "My post here"
}

到 URL:http://localhost:8888/place/1/posts

然后先获取地点,然后将帖子存储到它?

4

1 回答 1

4

当表示为 JSON 时,关系始终是列表或对象。在你的情况下:

{
  "text": "text",
  "place": {
    "id": 1
  }
}

这允许客户端应用程序解析代码保持一致 - 相关对象始终是对象,而不是合成字段(例如,place_id)。底层数据库确实place_id通过使用下划线连接关系名称及其主键名称来命名列,但这是一个未通过 API 公开的实现细节。

插入对象时,会插入外键,因为它们是表中的一列。因此,您可以这样编写操作方法:

@Operation.post()
Future<Response> createPost(@Bind.body() Post post) async {
  final query = new Query<Post>(context)
    ..values = post;

  final insertedPost = await query.insert();

  return new Response.ok(insertedPost);
}

如果您使用示例 JSON 和此代码,您将获得以下 SQL 查询:INSERT INTO _post (text, place_id) VALUES ('text', 1).

在插入关系的“有”端时,您必须将相关对象作为单独的查询插入。更新/插入查询只会在单个表上设置/插入值。如果它对您的 API 有意义,您可能需要发布以下位置 JSON:

{
  "name": "Place",
  "posts": [
    {"text": "text"}
  ]
}

您插入此对象图的代码可能如下所示:

await context.transaction((t) async {
  final q = Query<Place>(t)..values = body;
  final insertedPlace = await q.insert();
  await Future.wait(body.posts, (p) async {
    final postQuery = Query<Post>(t)
      ..values = p
      ..values.place.id = insertedPlace.id;
    return postQuery.insert();
  });
});

其他几个小注释:asMap已被删除并替换为as<T>or decode<T>@Column如果您不添加任何标志,您也不需要注释。表定义类型中声明的所有字段都是数据库列。瞬态字段在子类中声明,如果您希望它们成为 API 表面的一部分,ManagedObject可以使用注释。@Serialize()

于 2018-07-25T16:48:53.750 回答