fetch labels and highlights after items fetched in a search query

This commit is contained in:
Hongbo Wu 2023-10-04 14:54:12 +08:00
parent bb59ed757c
commit d4404b0248
7 changed files with 90 additions and 17 deletions

View file

@ -649,7 +649,6 @@ export const searchResolver = authorized<
size: first + 1, // fetch one more item to get next cursor
sort: searchQuery.sort,
includePending: true,
includeContent: params.includeContent ?? false,
...searchQuery,
},
uid
@ -738,7 +737,7 @@ export const updatesSinceResolver = authorized<
from: Number(startCursor),
size: size + 1, // fetch one more item to get next cursor
includeDeleted: true,
dateFilters: [{ field: 'updated_at', startDate }],
dateFilters: [{ field: 'updatedAt', startDate }],
sort,
},
uid

View file

@ -4,9 +4,21 @@
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { Subscription } from '../entity/subscription'
import { Article, PageType, SearchItem } from '../generated/graphql'
import {
Article,
Highlight,
Label,
PageType,
SearchItem,
} from '../generated/graphql'
import { findHighlightsByLibraryItemId } from '../services/highlights'
import { findLabelsByLibraryItemId } from '../services/labels'
import { findUploadFileById } from '../services/upload_file'
import { validatedDate, wordsCount } from '../utils/helpers'
import {
highlightDataToHighlight,
validatedDate,
wordsCount,
} from '../utils/helpers'
import { createImageProxyUrl } from '../utils/imageproxy'
import {
generateDownloadSignedUrl,
@ -467,9 +479,28 @@ export const functionResolvers = {
originalArticleUrl(item: { url: string }) {
return item.url
},
wordsCount(article: { wordCount?: number; content?: string }) {
if (article.wordCount) return article.wordCount
return article.content ? wordsCount(article.content) : undefined
wordsCount(item: { wordCount?: number; content?: string }) {
if (item.wordCount) return item.wordCount
return item.content ? wordsCount(item.content) : undefined
},
async highlights(
item: { id: string; highlights?: Highlight[] },
_: unknown,
ctx: WithDataSourcesContext
) {
if (item.highlights) return item.highlights
const highlights = await findHighlightsByLibraryItemId(item.id, ctx.uid)
return highlights.map(highlightDataToHighlight)
},
async labels(
item: { id: string; labels?: Label[] },
_: unknown,
ctx: WithDataSourcesContext
) {
if (item.labels) return item.labels
return findLabelsByLibraryItemId(item.id, ctx.uid)
},
},
Subscription: {

View file

@ -160,3 +160,21 @@ export const findHighlightById = async (
userId
)
}
export const findHighlightsByLibraryItemId = async (
libraryItemId: string,
userId: string
) => {
return authTrx(
async (tx) =>
tx.withRepository(highlightRepository).find({
where: { libraryItem: { id: libraryItemId } },
relations: {
user: true,
labels: true,
},
}),
undefined,
userId
)
}

View file

@ -2,6 +2,7 @@ import { FindOptionsWhere, In } from 'typeorm'
import { QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialEntity'
import { EntityLabel } from '../entity/entity_label'
import { Label } from '../entity/label'
import { LibraryItem } from '../entity/library_item'
import { createPubSubClient, EntityType } from '../pubsub'
import { authTrx } from '../repository'
import { CreateLabelInput, labelRepository } from '../repository/label'
@ -236,3 +237,28 @@ export const findLabelById = async (id: string, userId: string) => {
userId
)
}
export const findLabelsByLibraryItemId = async (
libraryItemId: string,
userId: string
) => {
return authTrx(
async (tx) =>
tx
.createQueryBuilder(Label, 'label')
.innerJoin(
EntityLabel,
'entityLabel',
'entityLabel.label_id = label.id'
)
.innerJoin(
LibraryItem,
'LibraryItem',
'LibraryItem.id = entityLabel.library_item_id'
)
.where('LibraryItem.id = :libraryItemId', { libraryItemId })
.getMany(),
undefined,
userId
)
}

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 } from '../repository'
import { authTrx, getColumns } from '../repository'
import { libraryItemRepository } from '../repository/library_item'
import { wordsCount } from '../utils/helpers'
import {
@ -275,10 +275,6 @@ export const searchLibraryItems = async (
async (tx) => {
const queryBuilder = tx
.createQueryBuilder(LibraryItem, 'library_item')
.leftJoinAndSelect('library_item.labels', 'labels')
.leftJoinAndSelect('library_item.highlights', 'highlights')
.leftJoinAndSelect('highlights.user', 'user')
.leftJoinAndSelect('user.profile', 'profile')
.leftJoinAndSelect('library_item.recommendations', 'recommendations')
.leftJoinAndSelect('recommendations.recommender', 'recommender')
.leftJoinAndSelect('recommendations.group', 'group')

View file

@ -11,6 +11,8 @@ CREATE INDEX IF NOT EXISTS highlight_library_item_id_idx ON omnivore.highlight (
CREATE INDEX IF NOT EXISTS user_profile_user_id_idx ON omnivore.user_profile (user_id);
CREATE INDEX IF NOT EXISTS library_item_user_id_idx ON omnivore.library_item (user_id);
-- create index for sorting
CREATE INDEX IF NOT EXISTS library_item_saved_at_idx ON omnivore.library_item (saved_at);
CREATE INDEX IF NOT EXISTS library_item_updated_at_idx ON omnivore.library_item (updated_at);
COMMIT;

View file

@ -4,13 +4,14 @@
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.highlight_library_item_id_idx;
DROP INDEX IF EXISTS omnivore.entity_labels_highlight_id_idx;
DROP INDEX IF EXISTS omnivore.entity_labels_library_item_id_idx;
DROP INDEX IF NOT EXISTS omnivore.user_profile_user_id_idx;
DROP INDEX IF NOT EXISTS omnivore.library_item_user_id_idx;
COMMIT;