fetch recommendations separately too

This commit is contained in:
Hongbo Wu 2023-10-04 16:24:31 +08:00
parent d4404b0248
commit f6c906201b
8 changed files with 85 additions and 12 deletions

View file

@ -198,4 +198,7 @@ export class LibraryItem {
@Column('text', { nullable: true })
note?: string | null
@Column('text', { nullable: true })
recommenderNames?: string[] | null
}

View file

@ -9,13 +9,16 @@ import {
Highlight,
Label,
PageType,
Recommendation,
SearchItem,
} from '../generated/graphql'
import { findHighlightsByLibraryItemId } from '../services/highlights'
import { findLabelsByLibraryItemId } from '../services/labels'
import { findRecommendationsByLibraryItemId } from '../services/recommendation'
import { findUploadFileById } from '../services/upload_file'
import {
highlightDataToHighlight,
recommandationDataToRecommendation,
validatedDate,
wordsCount,
} from '../utils/helpers'
@ -502,6 +505,15 @@ export const functionResolvers = {
return findLabelsByLibraryItemId(item.id, ctx.uid)
},
async recommendations(item: {
id: string
recommendations?: Recommendation[]
}) {
if (item.recommendations) return item.recommendations
const recommendations = await findRecommendationsByLibraryItemId(item.id)
return recommendations.map(recommandationDataToRecommendation)
},
},
Subscription: {
newsletterEmail(subscription: Subscription) {

View file

@ -6,7 +6,7 @@ import { Label } from '../entity/label'
import { LibraryItem, LibraryItemState } from '../entity/library_item'
import { BulkActionType } from '../generated/graphql'
import { createPubSubClient, EntityType } from '../pubsub'
import { authTrx, getColumns } from '../repository'
import { authTrx } from '../repository'
import { libraryItemRepository } from '../repository/library_item'
import { wordsCount } from '../utils/helpers'
import {
@ -245,12 +245,13 @@ const buildWhereClause = (
}
if (args.recommendedBy) {
queryBuilder.andWhere('recommendations IS NOT NULL')
// select all if * is provided
if (args.recommendedBy !== '*') {
if (args.recommendedBy === '*') {
// select all if * is provided
queryBuilder.andWhere(`library_item.recommender_names <> '{}'`)
} else {
// select only if the user is recommended by the provided user
queryBuilder.andWhere(
'(lower(recommender.name) = :recommendedBy OR lower(group.name) = :recommendedBy)',
'lower(library_item.recommender_names::text)::text[] && ARRAY[:recommendedBy]::text[]',
{
recommendedBy: args.recommendedBy.toLowerCase(),
}
@ -275,10 +276,6 @@ export const searchLibraryItems = async (
async (tx) => {
const queryBuilder = tx
.createQueryBuilder(LibraryItem, 'library_item')
.leftJoinAndSelect('library_item.recommendations', 'recommendations')
.leftJoinAndSelect('recommendations.recommender', 'recommender')
.leftJoinAndSelect('recommendations.group', 'group')
.leftJoinAndSelect('recommender.profile', 'recommender_profile')
.where('library_item.user_id = :userId', { userId })
// build the where clause

View file

@ -94,3 +94,15 @@ export const createRecommendation = async (
) => {
return getRepository(Recommendation).save(recommendation)
}
export const findRecommendationsByLibraryItemId = async (
libraryItemId: string
) => {
return getRepository(Recommendation).find({
where: { libraryItem: { id: libraryItemId } },
relations: {
group: true,
recommender: true,
}
})
}

View file

@ -208,7 +208,7 @@ export const highlightDataToHighlight = (
user: userDataToUser(highlight.user),
})
const recommandationDataToRecommendation = (
export const recommandationDataToRecommendation = (
recommendation: RecommendationData
): Recommendation => ({
...recommendation,

View file

@ -7,7 +7,7 @@ BEGIN;
DROP INDEX IF EXISTS omnivore.library_item_updated_at_idx;
DROP INDEX IF EXISTS omnivore.library_item_saved_at_idx;
DROP INDEX IF NOT EXISTS omnivore.user_profile_user_id_idx;
DROP INDEX IF EXISTS omnivore.user_profile_user_id_idx;
DROP INDEX IF EXISTS omnivore.highlight_library_item_id_idx;

View file

@ -0,0 +1,37 @@
-- Type: DO
-- Name: add_recommender_names_to_library_item
-- Description: Add recommender names field to library item table
BEGIN;
ALTER TABLE omnivore.library_item ADD COLUMN recommender_names text[] DEFAULT '{}'::text[];
CREATE OR REPLACE FUNCTION update_library_item_recommenders()
RETURNS trigger AS $$
BEGIN
-- update library_item recommender names from user and group table name column
UPDATE omnivore.library_item
SET recommender_names = (
SELECT array_agg(DISTINCT name)
FROM (
SELECT name
FROM omnivore.user
WHERE id = NEW.user_id
UNION
SELECT name
FROM omnivore.group
WHERE id = NEW.group_id
) AS recommender_names
)
WHERE id = NEW.library_item_id;
return NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER library_item_recommenders_update
AFTER INSERT ON omnivore.recommendation
FOR EACH ROW
EXECUTE FUNCTION update_library_item_recommenders();
COMMIT;

View file

@ -0,0 +1,12 @@
-- Type: UNDO
-- Name: add_recommender_names_to_library_item
-- Description: Add recommender names field to library item table
BEGIN;
DROP TRIGGER IF EXISTS library_item_recommenders_update ON omnivore.recommendation;
DROP FUNCTION IF EXISTS update_library_item_recommenders();
ALTER TABLE omnivore.library_item DROP COLUMN recommender_names;
COMMIT;