Replace native query with criteria api for feeds (#190)

This commit is contained in:
Kavin 2022-02-15 11:37:21 +00:00 committed by GitHub
parent 166e14cf71
commit 498849ec6b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 54 additions and 63 deletions

View file

@ -49,6 +49,7 @@ import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.Root; import javax.persistence.criteria.Root;
import java.io.IOException; import java.io.IOException;
import java.util.*; import java.util.*;
@ -728,26 +729,34 @@ public class ResponseHelper {
if (user != null) { if (user != null) {
@SuppressWarnings("unchecked") CriteriaBuilder cb = s.getCriteriaBuilder();
List<Object[]> queryResults = s.createNativeQuery(
"select Video.*, Channel.* from videos as Video left join channels as Channel on Video.uploader_id = Channel.uploader_id inner join users_subscribed on users_subscribed.channel = Channel.uploader_id where users_subscribed.subscriber = :user")
.setParameter("user", user.getId()).addEntity("Video", Video.class)
.addEntity("Channel", me.kavin.piped.utils.obj.db.Channel.class).getResultList();
List<FeedItem> feedItems = new ObjectArrayList<>(); // Get all videos from subscribed channels, with channel info
CriteriaQuery<Video> criteria = cb.createQuery(Video.class);
criteria.distinct(true);
var root = criteria.from(Video.class);
var userRoot = criteria.from(User.class);
root.fetch("channel", JoinType.LEFT);
queryResults.forEach(obj -> { criteria.select(root)
Video video = (Video) obj[0]; .where(cb.and(
me.kavin.piped.utils.obj.db.Channel channel = (me.kavin.piped.utils.obj.db.Channel) obj[1]; cb.isMember(root.get("channel"), userRoot.<Collection<String>>get("subscribed_ids")),
cb.equal(userRoot.get("id"), user.getId())
))
.orderBy(cb.desc(root.get("uploaded")));
feedItems.add(new FeedItem("/watch?v=" + video.getId(), video.getTitle(), List<StreamItem> feedItems = new ObjectArrayList<>();
rewriteURL(video.getThumbnail()), "/channel/" + channel.getUploaderId(), channel.getUploader(),
rewriteURL(channel.getUploaderAvatar()), video.getViews(), video.getDuration(), for (Video video : s.createQuery(criteria).list()) {
var channel = video.getChannel();
feedItems.add(new StreamItem("/watch?v=" + video.getId(), video.getTitle(),
rewriteURL(video.getThumbnail()), channel.getUploader(), "/channel/" + channel.getUploaderId(),
rewriteURL(channel.getUploaderAvatar()), null, null, video.getDuration(), video.getViews(),
video.getUploaded(), channel.isVerified())); video.getUploaded(), channel.isVerified()));
}
}); feedItems.sort(Comparator.<StreamItem>comparingLong(o -> o.uploaded).reversed());
feedItems.sort(Comparator.<FeedItem>comparingLong(o -> o.uploaded).reversed());
s.close(); s.close();
@ -776,21 +785,28 @@ public class ResponseHelper {
feed.setUri(Constants.FRONTEND_URL + "/feed"); feed.setUri(Constants.FRONTEND_URL + "/feed");
feed.setPublishedDate(new Date()); feed.setPublishedDate(new Date());
if (user.getSubscribed() != null && !user.getSubscribed().isEmpty()) { CriteriaBuilder cb = s.getCriteriaBuilder();
@SuppressWarnings("unchecked") // Get all videos from subscribed channels, with channel info
List<Object[]> queryResults = s.createNativeQuery( CriteriaQuery<Video> criteria = cb.createQuery(Video.class);
"select Video.*, Channel.* from videos as Video left join channels as Channel on Video.uploader_id = Channel.uploader_id inner join users_subscribed on users_subscribed.channel = Channel.uploader_id where users_subscribed.subscriber = :user") criteria.distinct(true);
.setParameter("user", user.getId()).addEntity("Video", Video.class) var root = criteria.from(Video.class);
.addEntity("Channel", me.kavin.piped.utils.obj.db.Channel.class).getResultList(); var userRoot = criteria.from(User.class);
root.fetch("channel", JoinType.LEFT);
queryResults.sort(Comparator.<Object[]>comparingLong(o -> ((Video) (o)[0]).getUploaded()).reversed()); criteria.select(root)
.where(cb.and(
cb.isMember(root.get("channel"), userRoot.<Collection<String>>get("subscribed_ids")),
cb.equal(userRoot.get("id"), user.getId())
))
.orderBy(cb.desc(root.get("uploaded")));
List<Video> videos = s.createQuery(criteria).list();
final List<SyndEntry> entries = new ObjectArrayList<>(); final List<SyndEntry> entries = new ObjectArrayList<>();
for (Object[] result : queryResults) { for (Video video : videos) {
Video video = (Video) result[0]; var channel = video.getChannel();
me.kavin.piped.utils.obj.db.Channel channel = (me.kavin.piped.utils.obj.db.Channel) result[1];
SyndEntry entry = new SyndEntryImpl(); SyndEntry entry = new SyndEntryImpl();
SyndPerson person = new SyndPersonImpl(); SyndPerson person = new SyndPersonImpl();
@ -808,7 +824,6 @@ public class ResponseHelper {
feed.setEntries(entries); feed.setEntries(entries);
}
s.close(); s.close();

View file

@ -1,24 +0,0 @@
package me.kavin.piped.utils.obj;
public class FeedItem {
public String url, title, thumbnail, uploaderUrl, uploaderName, uploaderAvatar;
public long views, duration, uploaded;
public boolean uploaderVerified;
public FeedItem(String url, String title, String thumbnail, String uploaderUrl, String uploaderName,
String uploaderAvatar, long views, long duration, long uploaded, boolean uploaderVerified) {
this.url = url;
this.title = title;
this.thumbnail = thumbnail;
this.uploaderUrl = uploaderUrl;
this.uploaderName = uploaderName;
this.uploaderAvatar = uploaderAvatar;
this.views = views;
this.duration = duration;
this.uploaded = uploaded;
this.uploaderVerified = uploaderVerified;
}
}