mirror of
https://github.com/miniflux/v2.git
synced 2025-06-27 16:36:00 +00:00
feat(storage): reduce the number of SQL queries when fetching entry enclosures
This commit is contained in:
parent
984a66b590
commit
82a6fe64ae
2 changed files with 65 additions and 11 deletions
|
@ -60,6 +60,51 @@ func (s *Storage) GetEnclosures(entryID int64) (model.EnclosureList, error) {
|
|||
return enclosures, nil
|
||||
}
|
||||
|
||||
func (s *Storage) GetEnclosuresForEntries(entryIDs []int64) (map[int64]model.EnclosureList, error) {
|
||||
query := `
|
||||
SELECT
|
||||
id,
|
||||
user_id,
|
||||
entry_id,
|
||||
url,
|
||||
size,
|
||||
mime_type,
|
||||
media_progression
|
||||
FROM
|
||||
enclosures
|
||||
WHERE
|
||||
entry_id = ANY($1)
|
||||
ORDER BY id ASC
|
||||
`
|
||||
|
||||
rows, err := s.db.Query(query, pq.Array(entryIDs))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("store: unable to fetch enclosures: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
enclosuresMap := make(map[int64]model.EnclosureList)
|
||||
for rows.Next() {
|
||||
var enclosure model.Enclosure
|
||||
err := rows.Scan(
|
||||
&enclosure.ID,
|
||||
&enclosure.UserID,
|
||||
&enclosure.EntryID,
|
||||
&enclosure.URL,
|
||||
&enclosure.Size,
|
||||
&enclosure.MimeType,
|
||||
&enclosure.MediaProgression,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("store: unable to scan enclosure row: %w", err)
|
||||
}
|
||||
|
||||
enclosuresMap[enclosure.EntryID] = append(enclosuresMap[enclosure.EntryID], &enclosure)
|
||||
}
|
||||
|
||||
return enclosuresMap, nil
|
||||
}
|
||||
|
||||
func (s *Storage) GetEnclosure(enclosureID int64) (*model.Enclosure, error) {
|
||||
query := `
|
||||
SELECT
|
||||
|
|
|
@ -277,7 +277,6 @@ func (e *EntryQueryBuilder) GetEntries() (model.Entries, error) {
|
|||
e.created_at,
|
||||
e.changed_at,
|
||||
e.tags,
|
||||
(SELECT true FROM enclosures WHERE entry_id=e.id LIMIT 1) as has_enclosure,
|
||||
f.title as feed_title,
|
||||
f.feed_url,
|
||||
f.site_url,
|
||||
|
@ -319,10 +318,12 @@ func (e *EntryQueryBuilder) GetEntries() (model.Entries, error) {
|
|||
defer rows.Close()
|
||||
|
||||
entries := make(model.Entries, 0)
|
||||
entryMap := make(map[int64]*model.Entry)
|
||||
var entryIDs []int64
|
||||
|
||||
for rows.Next() {
|
||||
var iconID sql.NullInt64
|
||||
var tz string
|
||||
var hasEnclosure sql.NullBool
|
||||
|
||||
entry := model.NewEntry()
|
||||
|
||||
|
@ -344,7 +345,6 @@ func (e *EntryQueryBuilder) GetEntries() (model.Entries, error) {
|
|||
&entry.CreatedAt,
|
||||
&entry.ChangedAt,
|
||||
pq.Array(&entry.Tags),
|
||||
&hasEnclosure,
|
||||
&entry.Feed.Title,
|
||||
&entry.Feed.FeedURL,
|
||||
&entry.Feed.SiteURL,
|
||||
|
@ -368,20 +368,13 @@ func (e *EntryQueryBuilder) GetEntries() (model.Entries, error) {
|
|||
return nil, fmt.Errorf("store: unable to fetch entry row: %v", err)
|
||||
}
|
||||
|
||||
if hasEnclosure.Valid && hasEnclosure.Bool && e.fetchEnclosures {
|
||||
entry.Enclosures, err = e.store.GetEnclosures(entry.ID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("store: unable to fetch enclosures for entry #%d: %w", entry.ID, err)
|
||||
}
|
||||
}
|
||||
|
||||
if iconID.Valid {
|
||||
entry.Feed.Icon.IconID = iconID.Int64
|
||||
} else {
|
||||
entry.Feed.Icon.IconID = 0
|
||||
}
|
||||
|
||||
// Make sure that timestamp fields contains timezone information (API)
|
||||
// Make sure that timestamp fields contain timezone information (API)
|
||||
entry.Date = timezone.Convert(tz, entry.Date)
|
||||
entry.CreatedAt = timezone.Convert(tz, entry.CreatedAt)
|
||||
entry.ChangedAt = timezone.Convert(tz, entry.ChangedAt)
|
||||
|
@ -391,7 +384,23 @@ func (e *EntryQueryBuilder) GetEntries() (model.Entries, error) {
|
|||
entry.Feed.UserID = entry.UserID
|
||||
entry.Feed.Icon.FeedID = entry.FeedID
|
||||
entry.Feed.Category.UserID = entry.UserID
|
||||
|
||||
entries = append(entries, entry)
|
||||
entryMap[entry.ID] = entry
|
||||
entryIDs = append(entryIDs, entry.ID)
|
||||
}
|
||||
|
||||
if e.fetchEnclosures && len(entryIDs) > 0 {
|
||||
enclosures, err := e.store.GetEnclosuresForEntries(entryIDs)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("store: unable to fetch enclosures: %w", err)
|
||||
}
|
||||
|
||||
for entryID, entryEnclosures := range enclosures {
|
||||
if entry, exists := entryMap[entryID]; exists {
|
||||
entry.Enclosures = entryEnclosures
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return entries, nil
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue