hashtags的最佳jpa实体模型

6ljaweal  于 2021-06-21  发布在  Mysql
关注(0)|答案(2)|浏览(317)

我需要为我的应用程序中的hashtags设计一个jpa实体模型,类似于instagram、twitter和stack overflow。我的申请。下面是我们的应用程序使用的特定于模式的点
标签应该属于一个问题
hashtag是特定于用户的。
每个用户都可以用相同的标签标记他们的问题
目前,我有两个用于上述模式的jpa模型
两种型号的通用表
表:问题
列:id、问题、描述等。,
表:用户
列:id、名称、角色、组等。,
模型1
表:问题\u散列\u标记
列:id、question\u id、user\u id、hashtag\u text
模型2
表:哈希标记
列:id,hastag\u text
表:用户标签
列:user\u id、hashtag\u id、question\u id
即使用户之间的hashtag相同,model 1也会有每一行。
模型2将有唯一的hashtag行,它在使用user\ hashtags的用户之间被引用。
我期待一个更好的和标准的模式超越这两个。
注意:问题可以根据标签和用户进行搜索

6rvt4ljy

6rvt4ljy1#

我们这里有三个“东西”:用户、问题和标签。在您的示例中,我会避免使用模型1,主要是因为它不灵活。当产品所有者后来决定向标签添加描述时会发生什么?如果下周产品所有者希望用户只从现有池中选择标记,会发生什么情况?虽然您的领域需求不完整且不明确,但更灵活的解决方案允许在模型之上实现未来的功能,而无需进行重大重构。既然如此,我肯定会认为hashtag是它自己的独立实体。
在第二个模型中,user\u hashtags表中表示的第三级关系似乎假设用户和问题之间存在可选的多对多关系。如果你的领域确实要求许多用户可以提出同样的问题,我认为模型2可以满足你的需要。更有可能的是,您的需求可能会明确限制多个用户编写单个特定问题的能力。如果是这样的话,模型中应该考虑到这些约束。另外,如果一个用户决定用5个不同的标签来标记一个问题,那么用户和问题之间的一对多关系将在每个标签的user\u hashtags表中声明5次。一个简单的查询来显示用户提出的问题,需要使用distinct,这会立即给设计敲响警钟。
假设用户和问题之间存在一对多关系,我将从“user\u hashtags”表中删除user\u id,而将user\u id作为外键放入questions表中。然后将user\u hashtags表重命名为question\u hashtags。这使得它既简单又高效,因为现在您只需查询一个表就可以获得由特定用户id编写的问题,而无需加入和添加谁知道数据库需要使用distinct筛选多少个重复项。现在还支持这样一种可能性:用户选择不为他们的问题添加hashtag(没有空白外键)。

注:

有许多因素会影响数据库的物理设计—不仅是“选择”访问模式,甚至可能是每个模式的相对频率。数据库写入与读取之间的比率、可以更新的内容以及与其他更新相关的频率等也会影响最终如何构造表。因此,没有“确定的”答案,只是一个基于一些假设和你的问题中提供的有限信息的答案。

vql8enpb

vql8enpb2#

hashtags已经是一种id了,所以不需要为它们提供一个专用的表。你只需要 questions 表格:

create table questions (
    id bigint not null constraint questions_pkey primary key,
    user_id bigint constraint fk_questions_users references users,
    question text not null;
)

以及 questions_hashtags 索引为的关系表 hashtag 字段:

create table questions_hashtags (
    question_id bigint not null fk_questions_hashtags_questions references questions,
    hashtag text not null,
    constraint uk_questions_hashtags unique (question_id, hashtag)
);

create index index_questions_hashtags_hashtag on questions_hashtags(hashtag);

(这里是postgresql方言。)
这些表简单地Map到单个(!)实体(不考虑 User 实体):

@Entity
@Table(name = "questions")
public class Question {
    @Id
    @GeneratedValue
    private Long id;

    @Column(nullable = false)
    private String question;

    @ManyToOne(optional = false)
    private User user;

    @CollectionTable(name = "questions_hashtags", joinColumns = @JoinColumn(name = "question_id"))
    @Column(name = "hashtag")
    @ElementCollection(fetch = FetchType.EAGER)
    @BatchSize(size = 20)
    private Set<String> hashtags = new HashSet<>();

    public Question(User user, String question) {
        this.user = user;
        this.question = question;
    }

    private Set<String> extractHashtags() {
      // extract hashtags from question to Set...
    }

    @PrePersist
    @PreUpdate
    private void populateHashtags() {
        hashtags.clear();
        hashtags.addAll(extractHashtags());
    }

    // other stuff
}

这是一个非常方便的模型。要使用标签创建和保存问题,只需执行以下操作:

questionRepo.save(new Question(user, question));

要获取所有hashtags,可以使用 questionRepo :

@Query("select distinct h as hashtag from Question q join q.hashtags h")
List<String> getAllHashtags();

要查找与特定hashtag相关的所有问题,可以使用以下查询方法:

@Query("select q from Question q join q.hashtags h where h = ?1")
List<Question> getQuestionsByHashtag(String hashtag);

要通过几个标签查找问题,可以使用以下方法:

@Query("select q from Question q join q.hashtags h where h in (?1)")
List<Question> getQuestionsByHashtag(Set<String> hashtags);

要查找与给定标签相关的用户,可以使用以下方法:

@Query("select distinct u from Question q join q.user u join q.hashtags h where h in (?1)")
List<User> getUsersByHashtag(Set<String> hashtags);

请参阅my rest service hashtag用法示例sb hashtag用法示例:

  1. POST /users -创建新用户
{
    "name": "user1"
}
  1. POST /questions -创建新问题
{
    "question": "How implement best JPA #entity #model for Hashtags?",
    "user": "/user/1"
}
  1. GET /hashtags -获取所有标签

GET/questions/search/by_hashtag ?hashtag=%23model -通过一个标签获取问题
5)
GET /questions/search/by_hashtags ?hashtags=%23entity,%23model -通过几个标签获取问题
6)
GET /users/search/by_hashtags ?hashtags=%23entity -通过多个标签获取用户
(其他方法如修补、删除也可用。)

相关问题