This commit is contained in:
Hongbo Wu 2023-12-06 13:52:17 +08:00
parent c8bd953cf3
commit 284697da5b
2 changed files with 64 additions and 57 deletions

View file

@ -745,8 +745,6 @@ export const updatesSinceResolver = authorized<
UpdatesSinceError,
QueryUpdatesSinceArgs
>(async (_obj, { since, first, after, sort: sortParams, folder }, { uid }) => {
const sort = sortParamsToSort(sortParams)
const startCursor = after || ''
const size = Math.min(first || 10, 100) // limit to 100 items
let startDate = new Date(since)
@ -754,18 +752,18 @@ export const updatesSinceResolver = authorized<
// for android app compatibility
startDate = new Date(0)
}
const sort = sortParamsToSort(sortParams)
// create a search query
const query = `updated:${startDate.toISOString()}${
folder ? ' in:' + folder : ''
}`
} sort:${sort.by}-${sort.order}`
const { libraryItems, count } = await searchLibraryItems(
{
from: Number(startCursor),
size: size + 1, // fetch one more item to get next cursor
includeDeleted: true,
sort,
query,
},
uid

View file

@ -94,13 +94,13 @@ export enum SortOrder {
}
export interface Sort {
by: SortBy
by: string
order?: SortOrder
}
interface Select {
column: string
alias: string
alias?: string
}
export const sortParamsToSort = (
@ -153,7 +153,7 @@ export const buildQuery = (
searchQuery: LiqeQuery,
parameters: ObjectLiteral[] = [],
selects: Select[] = [],
orders: { by: string; order?: SortOrder }[] = [],
orders: Sort[] = [],
useFolders = false
) => {
const escapeQueryWithParameters = (
@ -189,10 +189,8 @@ export const buildQuery = (
alias,
})
orders.push({
by: alias,
order: SortOrder.DESCENDING,
})
// always sort by rank first
orders.unshift({ by: alias, order: SortOrder.DESCENDING })
return escapeQueryWithParameters(
`websearch_to_tsquery('english', :${param}) @@ library_item.search_tsv`,
@ -388,8 +386,20 @@ export const buildQuery = (
default: {
// check for date ranges
const [start, end] = date.split('..')
startDate = start && start !== '*' ? new Date(start) : undefined
endDate = end && end !== '*' ? new Date(end) : undefined
// validate date
if (start && start !== '*') {
startDate = new Date(start)
if (!startDate.getTime()) {
throw new Error('Invalid start date.')
}
}
if (end && end !== '*') {
endDate = new Date(end)
if (!endDate.getTime()) {
throw new Error('Invalid end date.')
}
}
}
}
@ -627,24 +637,29 @@ export const searchLibraryItems = async (
args: SearchArgs,
userId: string
): Promise<{ libraryItems: LibraryItem[]; count: number }> => {
const { from = 0, size = 10, sort } = args
const { from = 0, size = 10 } = args
// default order is descending
const sortOrder = sort?.order || SortOrder.DESCENDING
// default sort by saved_at
const sortField = sort?.by || SortBy.SAVED
const selectColumns = getColumns(libraryItemRepository)
.map((column) => `library_item.${column}`)
const selects: Select[] = getColumns(libraryItemRepository)
.map((column) => ({ column: `library_item.${column}` }))
.filter(
(column) =>
column !== 'library_item.readableContent' &&
column !== 'library_item.originalContent'
(select) =>
select.column !== 'library_item.readableContent' &&
select.column !== 'library_item.originalContent'
)
let searchQuery: LiqeQuery | undefined
const parameters: ObjectLiteral[] = []
const orders: Sort[] = []
let query: string | null = null
if (args.query) {
searchQuery = parseSearchQuery(args.query)
const searchQuery = parseSearchQuery(args.query)
query = buildQuery(
searchQuery,
parameters,
selects,
orders,
args.useFolders
)
}
// add pagination and sorting
@ -652,34 +667,12 @@ export const searchLibraryItems = async (
async (tx) => {
const queryBuilder = tx
.createQueryBuilder(LibraryItem, 'library_item')
.select(selectColumns)
.where('library_item.user_id = :userId', { userId })
if (searchQuery) {
const parameters: ObjectLiteral[] = []
const selects: Select[] = []
const orders: Sort[] = []
const whereClause = buildQuery(
searchQuery,
parameters,
selects,
orders,
args.useFolders
)
whereClause &&
queryBuilder
.andWhere(whereClause)
.setParameters(parameters.reduce((a, b) => ({ ...a, ...b }), {}))
selects.forEach((select) => {
queryBuilder.addSelect(select.column, select.alias)
})
// add order by
orders.forEach((order) => {
queryBuilder.addOrderBy(order.by, order.order, 'NULLS LAST')
})
}
// add select
selects.forEach((select) => {
queryBuilder.addSelect(select.column, select.alias)
})
if (!args.includePending) {
queryBuilder.andWhere("library_item.state <> 'PROCESSING'")
@ -689,14 +682,30 @@ export const searchLibraryItems = async (
queryBuilder.andWhere("library_item.state <> 'DELETED'")
}
const libraryItems = await queryBuilder
.addOrderBy(`library_item.${sortField}`, sortOrder, 'NULLS LAST')
.skip(from)
.take(size)
.getMany()
if (query) {
// add where clause from query
queryBuilder
.andWhere(query)
.setParameters(parameters.reduce((a, b) => ({ ...a, ...b }), {}))
}
const count = await queryBuilder.getCount()
// default order by saved at descending
if (orders.length === 0) {
orders.push({
by: 'library_item.saved_at',
order: SortOrder.DESCENDING,
})
}
// add order by
orders.forEach((order) => {
queryBuilder.addOrderBy(order.by, order.order, 'NULLS LAST')
})
const libraryItems = await queryBuilder.skip(from).take(size).getMany()
return { libraryItems, count }
},
undefined,