Skip to content

Commit

Permalink
search-facets service refactored and schema added
Browse files Browse the repository at this point in the history
  • Loading branch information
theorm committed May 2, 2024
1 parent caebfd3 commit 8ffae62
Show file tree
Hide file tree
Showing 22 changed files with 1,677 additions and 544 deletions.
4 changes: 4 additions & 0 deletions src/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type { FromSchema, JSONSchemaDefinition } from '@feathersjs/schema'
import { Ajv, getValidator } from '@feathersjs/schema'
import type { RedisClientOptions } from 'redis'
import type { RateLimiterConfiguration } from './services/internal/rateLimiter/redis'
import { Sequelize } from 'sequelize'

export type RedisConfiguration = RedisClientOptions & { enable?: boolean; host?: string }

Expand All @@ -12,6 +13,9 @@ export interface Configuration {
redis?: RedisConfiguration
rateLimiter?: RateLimiterConfiguration & { enabled?: boolean }
publicApiPrefix?: string

// TODO: move to services:
sequelizeClient?: Sequelize
}

const configurationSchema: JSONSchemaDefinition = {
Expand Down
98 changes: 0 additions & 98 deletions src/hooks/resolvers.js

This file was deleted.

116 changes: 116 additions & 0 deletions src/hooks/resolvers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import lodash from 'lodash'
import Collection from '../models/collections.model'
import { HookContext } from '@feathersjs/feathers'
import { Service as SearchFacetService } from '../services/search-facets/search-facets.class'
import { ImpressoApplication } from '../types'
import { FindResponse } from '../models/common'
import { SearchFacet, SearchFacetBucket } from '../models/generated/schemas'
const debug = require('debug')('impresso/hooks/resolvers')

const supportedMethods = ['get', 'find']

const isSearchFacetBucket = (bucket: any): bucket is SearchFacetBucket => {
return typeof bucket.val === 'string'
}

const resultAsList = (result: FindResponse<SearchFacet> | SearchFacet | undefined): SearchFacet[] => {
if (result == null) return []

if ('data' in result && Array.isArray(result.data)) {
return result.data
} else {
return [result as SearchFacet]
}
}

const assertCorrectServiceAndMethods = (
hookName: string,
context: HookContext<ImpressoApplication, SearchFacetService>
) => {
if (!(context.service instanceof SearchFacetService))
throw new Error(`${hookName} hook can only be used with ${SearchFacetService.name} service`)

if (!supportedMethods.includes(context.method))
throw new Error(`${hookName} hook can only be used with methods: ${supportedMethods}. Got: ${context.method}`)
}

export const resolveTextReuseClusters = () => async (context: HookContext<ImpressoApplication, SearchFacetService>) => {
assertCorrectServiceAndMethods(resolveTextReuseClusters.name, context)

const items = resultAsList(context.result)

const uids = items
.filter(d => d.type === 'textReuseCluster')
.reduce((acc, d) => acc.concat(d.buckets.filter(isSearchFacetBucket).map(di => di.val)), [] as string[])

if (!uids.length) return

debug('resolveTextReuseClusters uids:', uids)
// get text reuse clusters as dictionary from text-reuse-clusters service
const index = await context.app
.service('text-reuse-passages')
.find({
query: {
filters: [{ type: 'textReuseCluster', q: uids }],
groupby: 'textReuseClusterId',
limit: uids.length,
},
})
.then(({ data }: { data: any }) => {
debug('resolveTextReuseClusters data:', data.length)
return lodash.keyBy(data, 'textReuseCluster.id')
})
.catch((err: Error) => {
console.error('hook resolveTextReuseClusters ERROR')
console.error(err)
})
debug('resolveTextReuseClusters index keys:', Object.keys(index))

items.forEach(d => {
if (d.type !== 'textReuseCluster') return
d.buckets.forEach(b => {
if (isSearchFacetBucket(b)) {
b.item = index[b.val]
}
})
})
}

export const resolveCollections = () => async (context: HookContext<ImpressoApplication, SearchFacetService>) => {
assertCorrectServiceAndMethods(resolveTextReuseClusters.name, context)

const items = resultAsList(context.result)

const uids = items
.filter(d => d.type === 'collection')
.reduce((acc, d) => acc.concat(d.buckets.filter(isSearchFacetBucket).map(di => di.val)), [] as string[])

if (!uids.length) return

// get collections as dictionary
const client = context.app.get('sequelizeClient')

const index = await Collection.sequelize(client)
.findAll({
where: {
uid: uids,
},
})
.then((rows: any[]) =>
lodash.keyBy(
rows.map(r => r.toJSON()),
'uid'
)
)
.catch((err: Error) => {
console.error('hook resolveCollections ERROR')
console.error(err)
})

items.forEach(d => {
if (d.type !== 'collection') return
d.buckets.filter(isSearchFacetBucket).forEach(b => {
b.item = index[b.val]
})
})
}
Loading

0 comments on commit 8ffae62

Please sign in to comment.