如何使用Java SDK在DynamoDB中建立多对多关系模型 [英] How to model many to many relationship in DynamoDB with Java SDK

查看:96
本文介绍了如何使用Java SDK在DynamoDB中建立多对多关系模型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经阅读了一些有关DynamoDB manyToMany关系的文章.

I have reviewed some article about DynamoDB manyToMany relationship.

据我了解; 应该有单个表,我需要使用复合主键.

As I understand it; There should be single table and I need to use composite primary key.


对于书籍项目; hashKey(partionKey)应该是书的ID;和RangeKey(sortKey)应该是作者ID; 对于作者项目; hashKey(partionKey)应该是作者ID;和RangeKey(sortKey)应该是书籍ID;

For book item ; hashKey(partionKey) should be book id; and RangeKey(sortKey) should be author id; For Author item; hashKey(partionKey) should be author id; and RangeKey(sortKey) should be book id;

我已经创建了这些模型;

I have created these models;

 @Data
 @DynamoDBTable(tableName = "author_book_table")
 public class Book {

    @Id
    private BookId id;

    private String name;

    private Integer pages;

 }



@Data
@DynamoDBTable(tableName = "author_book_table")
public class Author {

    @Id
    private AuthorId id;
    @DynamoDBAttribute
    private String name;

}

Id模型如下:

@Data
public class BookId {

    @DynamoDBHashKey
    private String bookId;

    @DynamoDBRangeKey
    private String authorId;
}


@Data
public class AuthorId {
    @DynamoDBHashKey
    private String authorId;
    @DynamoDBRangeKey
    private String bookId;
}

但是我无法想象如何使用它,如何按作者查询书籍或按作者查询书籍. 正确的方法是什么?

But I can’t imagine how to use it, how to query books by Author or authors by book. What is the correct way to do it?

我找不到有关Java关系的任何示例. 我还使用了Spring数据dynamoDB moodule.

I could not find any example for relationships on java. I also using Spring data dynamoDB moodule.

推荐答案

[旁注:您确定Spring Data dynamodb模块允许您在同一张表上读取/写入两个不同的@Data类吗?如果答案为否",那么您将需要使用两个单独的表.无论如何,我的答案的其余部分不受此影响(因为使用其他SDK时,您肯定可以在同一个DDB表中存储不止一种类型的项目)

[side note: Are you sure the spring data dynamodb module allows you to read/write two different @Data classes on the same table? If the answer is "no" then you will need to use two separate tables. Anyhow, the rest of my answer is not affected by that (because you can certainly do store more then one type of items in the same DDB table when using other SDKs]

我可以想到四个用例:

(a)给定一个作者的ID,您希望获得她所写的所有书籍的ID.

(a) given the ID of an author you want to get the IDs of all books she wrote

(b)给定作者ID,您希望获得她所写的所有书籍的名称

(b) given the ID of an author you want to get the names of all books she wrote

(c)给出了您要获取的图书的ID,以获取该图书的所有作者的ID

(c) given the ID of a book you you want to get the IDs of all authors of the book

(d)给出了您要获取的书的ID,以获取该书的所有作者的名字

(d) given the ID of a book you you want to get the names of all authors of the book

快速的答案是,给定此数据模型(a)和(c)即可通过单个查询轻松实现.但是,(b)和(d)不能通过单个查询来实现(请参阅下面的答案1).但是,DDB中的正确"方法是对事物进行建模(请参见下面的答案2)

The quick answer is that given this data model (a) and (c) can be easily achieved with a single query. However (b) and (d) cannot be achieved with a single query (see answer 1, below). However, the "right" approach in DDB is to model things differently (see answer 2, below)

答案1

此处所述,当您执行在DDB表上,您可以为其分配分区键(又名:哈希键).查询将返回所有带有按范围键排序的分区键的项目.由于每个作者项都有一个书ID(作为范围键),因此,当您传递作者ID时,您将获得所有书ID.同样,如果查询给定的书ID,您将获得所有作者ID.

As stated here when you do a query on a DDB table you can give it a partition key (aka: hash key). The query will return all items with that partition key sorted by the range key. As each author item has (as a range key) a book ID this means you will get all book IDs when you pass in an author ID. Similarly, if query on a given book ID you will get all author IDs.

如果您还想获取书名(从给定的作者ID),则必须首先获取所有书ID(如上一段所述),然后使用 100项上限,您可能需要进行多次BatchGetItem调用. (当然,此解决方案也可以在另一个方向上起作用:book-> author,您只需要在心理上将作者替换为author,反之亦然)

If you also want to get the book names (from a given author ID) you will have first to get all book IDs (as explained in the previous paragraph) and then use BatchGetItem to get the individual book items. Note that BatchGetItem an upper limit of 100 items so you may need to do multiple BatchGetItem calls to. (of course, this solution will also work in the other direction: book -> author, you just need to mentally replace book with author and vice-versa)

答案2

在DDB和许多其他NoSql数据库中,您可以使用数据的非规范化(即在多个项目之间重复相同的信息)来对数据进行整形,使其已经以适合您检索的方式进行存储用例.在这里,它归结为只有一种类型的项目,其中既包含作者详细信息又包含书籍详细信息.

In DDB, and in many other NoSql databases, you can use denormalization of the data (that is duplicate the same piece of information across multiple items) to shape the data such that it is already stored in a way that fits your retrieval use cases. In here, it boildown to having a single type of items which contains both author details and book details.

@Data
@DynamoDBTable(tableName = "author_book_table")
public class Book {

  @DynamoDBHashKey
  @DynamoDBIndexRangeKey(globalSecondaryIndexName="ByAuthor")
  private String bookId;

  @DynamoDBRangeKey
  @DynamoDBIndexHashKey(globalSecondaryIndexName="ByAuthor")
  private String authorId;

  private String bookName;
  private String authorName;
  private Integer pages;
}

使用此数据模型,您仍然可以查询书籍的所有作者,并发出有关书籍ID的查询.查询结果返回的项目将包含所有作者姓名.对于另一个方向(作者ID->书籍),您也需要对查询进行操作,但这一次是针对您需要定义的全局二级索引(ByAuthor).在该索引中,角色是相反的:作者ID是哈希键,书ID是范围键.

Using this data model you can still query all authors of a book issuing a query on the book ID. The items returned by the query result will contain all author names. For the other direction (author ID -> book) you also need do to a query but this time against a global secondary index (ByAuthor) which you need to define. In this index, the roles are reversed: the author ID is the hash key and the book ID is the range key.

缺点是,当一条数据发生更改时,您需要更新多个记录.例如,如果您需要将作者ID'100'的名称从'Alice'更新为'Beth',则需要找到作者ID为'100'的 all 项目,并在其中更新作者名称.同样,如果需要更新表的数量,则需要更新多个项目(如果这本书有三位作者,那么将需要更新具有该书ID的三个项目).

The downside is that you need to update multiple records when a piece of data changes. For instance, if you need to update the name of author ID '100' from 'Alice' to 'Beth' you need to find all items with author ID '100' and update the author name there. Similarly, if you need to update the number of tables, you will need to update multiple items (if this book has three authors, there will be three items with that book ID which needs to be updated).

重要提示:您可以从应用程序/服务中发布此更新.但是,您需要为服务(或基础硬件)在更新过程中失败的情况做好准备.这很可能导致数据不一致(在某些项目中作者名称为"Beth",但在某些项目中仍为"Alice"). 交易可以为您提供帮助,但仅限于更新25个项目.如果您无法在单个事务中进行更新,则需要采取纠正措施:例如,您可以定期扫描数据库并修复发现的任何不一致之处.最重要的是,您可以让服务主动检查其在常规"操作期间获取的项目中的不一致之处.如果发现不一致,则可以针对这些特定项目启动修复程序.

Important: you can issue this updates from your application/service. However, you need to be prepared to a situation where your service (or the underlying hardware) fail mid update. This is likely to result in inconsistent data (in some items the author name is 'Beth' but in some items it is still 'Alice'). Transaction can help you but they are limited to updating 25 items. if you cannot update in a single transaction you will need to take corrective measurement: for instance, you can periodically scan the DB and fix any inconsistencies you find. On top of that, you can have the service proactively check for inconsistencies in the item it fetches during its "regular" operation. If it finds an inconsistency it can launch a fix on those specific items.

这篇关于如何使用Java SDK在DynamoDB中建立多对多关系模型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆