add score to home item
This commit is contained in:
@ -1302,6 +1302,7 @@ export type HomeItem = {
|
||||
likeCount?: Maybe<Scalars['Int']>;
|
||||
previewContent?: Maybe<Scalars['String']>;
|
||||
saveCount?: Maybe<Scalars['Int']>;
|
||||
score: Scalars['Float'];
|
||||
seen_at?: Maybe<Scalars['Date']>;
|
||||
slug?: Maybe<Scalars['String']>;
|
||||
source?: Maybe<HomeItemSource>;
|
||||
@ -6043,6 +6044,7 @@ export type HomeItemResolvers<ContextType = ResolverContext, ParentType extends
|
||||
likeCount?: Resolver<Maybe<ResolversTypes['Int']>, ParentType, ContextType>;
|
||||
previewContent?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
|
||||
saveCount?: Resolver<Maybe<ResolversTypes['Int']>, ParentType, ContextType>;
|
||||
score?: Resolver<ResolversTypes['Float'], ParentType, ContextType>;
|
||||
seen_at?: Resolver<Maybe<ResolversTypes['Date']>, ParentType, ContextType>;
|
||||
slug?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
|
||||
source?: Resolver<Maybe<ResolversTypes['HomeItemSource']>, ParentType, ContextType>;
|
||||
|
||||
@ -1171,6 +1171,7 @@ type HomeItem {
|
||||
likeCount: Int
|
||||
previewContent: String
|
||||
saveCount: Int
|
||||
score: Float!
|
||||
seen_at: Date
|
||||
slug: String
|
||||
source: HomeItemSource
|
||||
|
||||
@ -5,7 +5,7 @@ import { User } from '../entity/user'
|
||||
import { redisDataSource } from '../redis_data_source'
|
||||
import { findUnseenPublicItems } from '../services/home'
|
||||
import { searchLibraryItems } from '../services/library_item'
|
||||
import { Feature, getScores, ScoreApiResponse } from '../services/score'
|
||||
import { Feature, getScores } from '../services/score'
|
||||
import { findSubscriptionsByNames } from '../services/subscriptions'
|
||||
import { findActiveUser } from '../services/user'
|
||||
import { lanaugeToCode } from '../utils/helpers'
|
||||
@ -34,7 +34,7 @@ interface Candidate {
|
||||
siteIcon?: string
|
||||
siteName?: string
|
||||
folder?: string
|
||||
score?: number
|
||||
score: number
|
||||
publishedAt?: Date
|
||||
subscription?: {
|
||||
name: string
|
||||
@ -45,6 +45,7 @@ interface Candidate {
|
||||
interface Item {
|
||||
id: string
|
||||
type: string
|
||||
score: number
|
||||
}
|
||||
|
||||
interface Section {
|
||||
@ -71,7 +72,7 @@ const libraryItemToCandidate = (
|
||||
siteName: item.siteName || undefined,
|
||||
siteIcon: item.siteIcon || undefined,
|
||||
folder: item.folder,
|
||||
score: item.score,
|
||||
score: item.score || 0,
|
||||
publishedAt: item.publishedAt || undefined,
|
||||
subscription: subscriptions.find(
|
||||
(subscription) =>
|
||||
@ -100,6 +101,7 @@ const publicItemToCandidate = (item: PublicItem): Candidate => ({
|
||||
name: item.source.name,
|
||||
type: item.source.type,
|
||||
},
|
||||
score: 0,
|
||||
})
|
||||
|
||||
const selectCandidates = async (user: User): Promise<Array<Candidate>> => {
|
||||
@ -157,14 +159,7 @@ const rankCandidates = async (
|
||||
userId: string,
|
||||
candidates: Array<Candidate>
|
||||
): Promise<Array<Candidate>> => {
|
||||
if (candidates.length <= 10) {
|
||||
// no need to rank if there are less than 10 candidates
|
||||
return candidates
|
||||
}
|
||||
|
||||
const unscoredCandidates = candidates.filter(
|
||||
(item) => item.score === undefined
|
||||
)
|
||||
const unscoredCandidates = candidates.filter((item) => item.score === 0)
|
||||
|
||||
const data = {
|
||||
user_id: userId,
|
||||
@ -190,21 +185,13 @@ const rankCandidates = async (
|
||||
}
|
||||
|
||||
const newScores = await getScores(data)
|
||||
const preCalculatedScores = candidates
|
||||
.filter((item) => item.score !== undefined)
|
||||
.reduce((acc, item) => {
|
||||
acc[item.id] = item.score as number
|
||||
return acc
|
||||
}, {} as ScoreApiResponse)
|
||||
const scores = { ...preCalculatedScores, ...newScores }
|
||||
// update scores for candidates
|
||||
candidates.forEach((item) => {
|
||||
item.score = newScores[item.id] || 0
|
||||
})
|
||||
|
||||
// rank candidates by score in ascending order
|
||||
candidates.sort((a, b) => {
|
||||
const scoreA = scores[a.id] || 0
|
||||
const scoreB = scores[b.id] || 0
|
||||
|
||||
return scoreA - scoreB
|
||||
})
|
||||
candidates.sort((a, b) => a.score - b.score)
|
||||
|
||||
return candidates
|
||||
}
|
||||
@ -360,6 +347,7 @@ const mixHomeItems = (rankedHomeItems: Array<Candidate>): Array<Section> => {
|
||||
items: batch.slice(0, 5).map((item) => ({
|
||||
id: item.id,
|
||||
type: item.type,
|
||||
score: item.score,
|
||||
})),
|
||||
layout: 'quick links',
|
||||
})
|
||||
@ -367,7 +355,7 @@ const mixHomeItems = (rankedHomeItems: Array<Candidate>): Array<Section> => {
|
||||
// create a section for each long item
|
||||
sections.push(
|
||||
...batch.slice(5).map((item) => ({
|
||||
items: [{ id: item.id, type: item.type }],
|
||||
items: [{ id: item.id, type: item.type, score: item.score }],
|
||||
layout: 'long',
|
||||
}))
|
||||
)
|
||||
@ -391,6 +379,11 @@ export const updateHome = async (data: UpdateHomeJobData) => {
|
||||
const candidates = await selectCandidates(user)
|
||||
logger.info(`Found ${candidates.length} candidates`)
|
||||
|
||||
if (candidates.length <= 10) {
|
||||
logger.info('Not enough candidates found')
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: integrity check on candidates
|
||||
|
||||
logger.info('Ranking candidates')
|
||||
|
||||
@ -634,7 +634,11 @@ export const functionResolvers = {
|
||||
HomeSection: {
|
||||
async items(
|
||||
section: {
|
||||
items: Array<{ id: string; type: 'library_item' | 'public_item' }>
|
||||
items: Array<{
|
||||
id: string
|
||||
type: 'library_item' | 'public_item'
|
||||
score: number
|
||||
}>
|
||||
},
|
||||
_: unknown,
|
||||
ctx: WithDataSourcesContext
|
||||
@ -685,6 +689,7 @@ export const functionResolvers = {
|
||||
siteName: libraryItem.siteName,
|
||||
siteIcon: libraryItem.siteIcon,
|
||||
slug: libraryItem.slug,
|
||||
score: item.score,
|
||||
}
|
||||
}
|
||||
|
||||
@ -711,6 +716,7 @@ export const functionResolvers = {
|
||||
likeCount: publicItem.stats.likeCount,
|
||||
saveCount: publicItem.stats.saveCount,
|
||||
source: publicItem.source,
|
||||
score: item.score,
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@ -3137,6 +3137,7 @@ const schema = gql`
|
||||
canShare: Boolean
|
||||
canArchive: Boolean
|
||||
canDelete: Boolean
|
||||
score: Float!
|
||||
}
|
||||
|
||||
type HomeSection {
|
||||
|
||||
Reference in New Issue
Block a user