最常用标签的 NamedQuery
NamedQuery for most used tags
假设我有以下 2 类:
@Entity
class Article {
@Id
int id;
@ManyToMany(mappedBy="articles")
List<Tag> tags;
}
@Entity
@NamedQueries({
@NamedQuery(name = "Tag.trends", query = "SELECT t FROM Tag t") // Some magic stuff here..
})
class Tag {
@Id
String name;
@ManyToMany
List<Articles> articles;
}
现在我想为 select 最常用的标签创建命名查询。
所以这需要 join、count 和 order by。但我似乎无法弄清楚。
问题:
我怎样才能 select 最常用的标签?
例如,如果以下文章具有以下标签:
Article: Tags
0: A, B
1: A
2: C
3: A, C
输出
A // 3 times
C // 2 times
B // 1 time
在这些类型的问题上逆向工作。从 SQL 查询开始:
select
count(t.name), t.name
from article a
join article_tags ats
join tag t
where
a.id=ats.article_id
and ats.tag_id = t.id
group by
t.name
order by
count(t.name)
desc;
那么 JPQL 应该或多或少地遵循:
List<Tuple> t = em.createQuery("select t.name as name, count(t.name) as count from Article a join a.tags t group by (t.name) order by count(t.name) desc", Tuple.class).getResultList();
t.stream().forEach((tp)-> {
System.out.println("Count of " + tp.get("name") + " = " + tp.get("count"));
});
这给了我以下输出:
Hibernate: select tag2_.name as col_0_0_, count(tag2_.name) as col_1_0_ from Article article0_ inner join Tag_Article tags1_ on article0_.id=tags1_.articles_id inner join Tag tag2_ on tags1_.tags_id=tag2_.id group by tag2_.name order by count(tag2_.name) desc
Count of A = 2
Count of B = 1
Count of C = 1
更新:如果您想要标签列表,只需将元组的第一个元素更改为标签即可。当然,如果你愿意,你可以忽略计数:
List<Tag> t = em.createQuery("select t from Article a join a.tags t group by (t.name) order by count(t.name) desc", Tag.class).getResultList();
t.stream().forEach((tag)-> {
System.out.println("Tag = " + tag.getName());
});
并得到以下输出:
Hibernate: select tag2_.id as id1_1_, tag2_.name as name2_1_ from Article article0_ inner join Tag_Article tags1_ on article0_.id=tags1_.articles_id inner join Tag tag2_ on tags1_.tags_id=tag2_.id group by tag2_.name order by count(tag2_.name) desc
Tag = A
Tag = B
Tag = C
您可以使用类似
的方式实现您想要的效果
SELECT t FROM Tag t ORDER BY SIZE(t.articles) ASC
这将为您带来按文章数量排序的标签列表。
假设我有以下 2 类:
@Entity
class Article {
@Id
int id;
@ManyToMany(mappedBy="articles")
List<Tag> tags;
}
@Entity
@NamedQueries({
@NamedQuery(name = "Tag.trends", query = "SELECT t FROM Tag t") // Some magic stuff here..
})
class Tag {
@Id
String name;
@ManyToMany
List<Articles> articles;
}
现在我想为 select 最常用的标签创建命名查询。
所以这需要 join、count 和 order by。但我似乎无法弄清楚。
问题: 我怎样才能 select 最常用的标签?
例如,如果以下文章具有以下标签:
Article: Tags
0: A, B
1: A
2: C
3: A, C
输出
A // 3 times
C // 2 times
B // 1 time
在这些类型的问题上逆向工作。从 SQL 查询开始:
select
count(t.name), t.name
from article a
join article_tags ats
join tag t
where
a.id=ats.article_id
and ats.tag_id = t.id
group by
t.name
order by
count(t.name)
desc;
那么 JPQL 应该或多或少地遵循:
List<Tuple> t = em.createQuery("select t.name as name, count(t.name) as count from Article a join a.tags t group by (t.name) order by count(t.name) desc", Tuple.class).getResultList();
t.stream().forEach((tp)-> {
System.out.println("Count of " + tp.get("name") + " = " + tp.get("count"));
});
这给了我以下输出:
Hibernate: select tag2_.name as col_0_0_, count(tag2_.name) as col_1_0_ from Article article0_ inner join Tag_Article tags1_ on article0_.id=tags1_.articles_id inner join Tag tag2_ on tags1_.tags_id=tag2_.id group by tag2_.name order by count(tag2_.name) desc
Count of A = 2
Count of B = 1
Count of C = 1
更新:如果您想要标签列表,只需将元组的第一个元素更改为标签即可。当然,如果你愿意,你可以忽略计数:
List<Tag> t = em.createQuery("select t from Article a join a.tags t group by (t.name) order by count(t.name) desc", Tag.class).getResultList();
t.stream().forEach((tag)-> {
System.out.println("Tag = " + tag.getName());
});
并得到以下输出:
Hibernate: select tag2_.id as id1_1_, tag2_.name as name2_1_ from Article article0_ inner join Tag_Article tags1_ on article0_.id=tags1_.articles_id inner join Tag tag2_ on tags1_.tags_id=tag2_.id group by tag2_.name order by count(tag2_.name) desc
Tag = A
Tag = B
Tag = C
您可以使用类似
的方式实现您想要的效果SELECT t FROM Tag t ORDER BY SIZE(t.articles) ASC
这将为您带来按文章数量排序的标签列表。