【问题标题】:How to insert a record with a Relationship如何插入具有关系的记录
【发布时间】:2018-07-24 16:44:54
【问题描述】:

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

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

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

我有以下型号:

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

我尝试保存帖子,但只能存储地点对象,而不是地点 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"
}

到网址:http://localhost:8888/place/1/posts

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

【问题讨论】:

    标签: dart aqueduct


    【解决方案1】:

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

    【讨论】:

    • 另外,如果你确实想要一个像place_id这样的合成字段:class Post extends ManagedObject&lt;_Post&gt; implements _Post { ... @Serialize() set place_id(int id) { place = Place()..id = id; } @Serialize() int get place_id =&gt; place?.id; }
    • 哇,太棒了。对此进行了很多思考。尤其是对象图。竖起大拇指,非常感谢您回答我所有的问题。 Aqueduct 真的是一个很棒的产品。
    猜你喜欢
    • 2014-09-16
    • 1970-01-01
    • 2015-03-02
    • 1970-01-01
    • 2013-05-02
    • 1970-01-01
    • 1970-01-01
    • 2010-10-29
    • 1970-01-01
    相关资源
    最近更新 更多