如何插入带有关系的记录

时间:2018-07-24 16:44:54

标签: dart aqueduct

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

我有地方。我想存储到此地点的用户的帖子。因此,一个地方可以有很多职位。帖子属于一个地方。

我正在使用Aqueduct 3.0 Pre-Release。

我有以下型号:

place.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;
}

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

也没有关系,我无法存储place_id,因为似乎渡槽将_视为特殊内容。我不能使用带有下划线的数据库属性吗?

有没有可以解释这一点的例子?

  @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"
}

到以下URL:http://localhost:8888/posts

发送这样的消息会更好吗?

{
    "text": "My post here"
}

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

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

1 个答案:

答案 0 :(得分:2)

当表示为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>decode<T>。如果您不添加任何标志,则也不需要@Column批注。表定义类型中声明的所有字段都是数据库列。临时字段在ManagedObject子类中声明,如果希望它们成为API表面的一部分,则可以用@Serialize()进行注释。