如何查询与一个用户在联接表中共享n个记录数量的用户列表

发布于 2025-01-18 09:07:48 字数 1796 浏览 0 评论 0原文

我有一个实体(用户),它有一个曲目列表。我想使用一个用户的 id 查询与该用户共享 N 个曲目的所有用户。我使用 Spring Data JPA 作为我的数据层。 我已经有一个本机查询正在执行我想要的操作,但它返回用户的 id 列表。我想改为获取列表。 这是我的用户实体:

@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Table(name = "user")
public class User {
    @Id
    private String id;

    private String email;

    private String country;

    @ElementCollection
    @CollectionTable(name = "user_top_tracks",
            joinColumns = @JoinColumn(name = "user_id"))
    @Column(name = "track_id")
    @JsonIgnore
    private List<String> tracks;

    @ElementCollection
    @CollectionTable(name = "user_top_artists",
            joinColumns = @JoinColumn(name = "user_id"))
    @Column(name = "artist_id")
    @JsonIgnore
    private List<String> artists;

    @ElementCollection
    @CollectionTable(name = "matches",
            joinColumns = @JoinColumn(name = "user_id"))
    @Column(name = "match")
    @JsonIgnore
    private List<String> matches;

    @JsonIgnore
    @OneToOne(fetch = FetchType.LAZY, mappedBy = "user", cascade = CascadeType.ALL)
    @PrimaryKeyJoinColumn
    private Token token;
}

我现在的查询(返回列表):

 @Query(value = "SELECT that.user_id " +
            "FROM user_top_tracks AS this INNER JOIN user_top_tracks " +
            "AS that ON that.user_id <> this.user_id " +
            "AND that.track_id = this.track_id WHERE this.user_id = ?1 " +
            "GROUP BY that.user_id HAVING COUNT(*) >= ?2", nativeQuery = true)
    List<String> getMatches(String userId, int matchingTracks);

数据库架构

对现在我编写了一个方法,用于遍历 ids 的返回列表,获取它们,然后将它们添加到用户列表中。它工作正常,但我想让它返回用户列表。

I have an entity (user) that has a List of tracks. I'd like to query all users that share N number of tracks with one user using his id. I'm using Spring Data JPA for my data layer.
I already have a native query that is doing what I want but it's returning a List of ids for the users. I would like to get List instead.
This is my user entity:

@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Table(name = "user")
public class User {
    @Id
    private String id;

    private String email;

    private String country;

    @ElementCollection
    @CollectionTable(name = "user_top_tracks",
            joinColumns = @JoinColumn(name = "user_id"))
    @Column(name = "track_id")
    @JsonIgnore
    private List<String> tracks;

    @ElementCollection
    @CollectionTable(name = "user_top_artists",
            joinColumns = @JoinColumn(name = "user_id"))
    @Column(name = "artist_id")
    @JsonIgnore
    private List<String> artists;

    @ElementCollection
    @CollectionTable(name = "matches",
            joinColumns = @JoinColumn(name = "user_id"))
    @Column(name = "match")
    @JsonIgnore
    private List<String> matches;

    @JsonIgnore
    @OneToOne(fetch = FetchType.LAZY, mappedBy = "user", cascade = CascadeType.ALL)
    @PrimaryKeyJoinColumn
    private Token token;
}

The query I have right now (returning List):

 @Query(value = "SELECT that.user_id " +
            "FROM user_top_tracks AS this INNER JOIN user_top_tracks " +
            "AS that ON that.user_id <> this.user_id " +
            "AND that.track_id = this.track_id WHERE this.user_id = ?1 " +
            "GROUP BY that.user_id HAVING COUNT(*) >= ?2", nativeQuery = true)
    List<String> getMatches(String userId, int matchingTracks);

Database schema

Right now I wrote a method that goes over the return list of ids, fetches them and then adds them to a List of users. It's working fine but I'd like to just make it return a List of users instead.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

戈亓 2025-01-25 09:07:48

您只需要再添加一个加入

@Query(value = "SELECT usr.* " +
        "FROM user_top_tracks AS this INNER JOIN user_top_tracks " +
        "AS that ON that.user_id <> this.user_id " +
        "AND that.track_id = this.track_id "+
        "JOIN user as usr on  that.user_id = usr.id"
         "WHERE this.user_id = ?1 " +
        "GROUP BY that.user_id HAVING COUNT(*) >= ?2", User.class )
List<User> getMatches(String userId, int matchingTracks);

,但我认为您也可以使用JPQL

You just need to add one more join

@Query(value = "SELECT usr.* " +
        "FROM user_top_tracks AS this INNER JOIN user_top_tracks " +
        "AS that ON that.user_id <> this.user_id " +
        "AND that.track_id = this.track_id "+
        "JOIN user as usr on  that.user_id = usr.id"
         "WHERE this.user_id = ?1 " +
        "GROUP BY that.user_id HAVING COUNT(*) >= ?2", User.class )
List<User> getMatches(String userId, int matchingTracks);

But I think you can also use JPQL

青衫儰鉨ミ守葔 2025-01-25 09:07:48

我最终做到了这一点并且工作正常。
如果我找到更好的解决方案,我会更新它。

    @Query(value ="SELECT * from user where id IN ("+
            "SELECT that.user_id " +
            "FROM user_top_tracks AS this INNER JOIN user_top_tracks " +
            "AS that ON that.user_id <> this.user_id " +
            "AND that.track_id = this.track_id WHERE this.user_id = ?1 " +
            "GROUP BY that.user_id HAVING COUNT(*) >= ?2 )", nativeQuery = true)
    List<User> getMatches(String userId, int matchingTracks);

I ended up doing this and it's working fine.
If i find any better solutions i'll update it.

    @Query(value ="SELECT * from user where id IN ("+
            "SELECT that.user_id " +
            "FROM user_top_tracks AS this INNER JOIN user_top_tracks " +
            "AS that ON that.user_id <> this.user_id " +
            "AND that.track_id = this.track_id WHERE this.user_id = ?1 " +
            "GROUP BY that.user_id HAVING COUNT(*) >= ?2 )", nativeQuery = true)
    List<User> getMatches(String userId, int matchingTracks);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文