feat(search): omit default sort while searching so results rank by relevance
The web client always sent sort_by/order_by (the view's default sort), so the backend's userProvidedSort flag was always true and the new BM25 relevance ranking never engaged from the web app. When a search is active and the user has not explicitly chosen a sort, omit the sort entirely so the backend ranks results by relevance. An explicit user sort still suppresses ranking and non-search browsing is unchanged.
This commit is contained in:
parent
6f6f91bd28
commit
a2cb2826d0
|
|
@ -0,0 +1,83 @@
|
||||||
|
import {describe, it, expect, beforeEach, vi} from 'vitest'
|
||||||
|
import {defineComponent, h, nextTick} from 'vue'
|
||||||
|
import {mount, flushPromises} from '@vue/test-utils'
|
||||||
|
import {setActivePinia, createPinia} from 'pinia'
|
||||||
|
import {createRouter, createMemoryHistory, type Router} from 'vue-router'
|
||||||
|
|
||||||
|
const getAll = vi.fn(async () => [])
|
||||||
|
vi.mock('@/services/taskCollection', async (importOriginal) => {
|
||||||
|
const actual = await importOriginal<typeof import('@/services/taskCollection')>()
|
||||||
|
return {
|
||||||
|
...actual,
|
||||||
|
default: class {
|
||||||
|
loading = false
|
||||||
|
totalPages = 1
|
||||||
|
getAll = getAll
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
import {useTaskList} from './useTaskList'
|
||||||
|
|
||||||
|
// The second positional argument passed to TaskCollectionService.getAll carries
|
||||||
|
// the sort_by/order_by the backend uses to decide whether to rank by relevance.
|
||||||
|
function lastRequestParams(): Record<string, unknown> {
|
||||||
|
return getAll.mock.calls.at(-1)?.[1] as Record<string, unknown>
|
||||||
|
}
|
||||||
|
|
||||||
|
async function mountTaskList(query: Record<string, string>): Promise<Router> {
|
||||||
|
const router = createRouter({
|
||||||
|
history: createMemoryHistory(),
|
||||||
|
routes: [{path: '/', name: 'home', component: {render: () => null}}],
|
||||||
|
})
|
||||||
|
await router.push({path: '/', query})
|
||||||
|
await router.isReady()
|
||||||
|
|
||||||
|
const TestComponent = defineComponent({
|
||||||
|
setup() {
|
||||||
|
useTaskList(() => 1, () => 1)
|
||||||
|
return () => h('div')
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
mount(TestComponent, {global: {plugins: [router]}})
|
||||||
|
await flushPromises()
|
||||||
|
await nextTick()
|
||||||
|
return router
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('useTaskList sort handling for relevance ranking', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
setActivePinia(createPinia())
|
||||||
|
getAll.mockClear()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('omits the sort while searching with the default sort so the backend ranks by relevance', async () => {
|
||||||
|
await mountTaskList({s: 'find me'})
|
||||||
|
|
||||||
|
const params = lastRequestParams()
|
||||||
|
expect(params.s).toBe('find me')
|
||||||
|
expect(params.sort_by).toEqual([])
|
||||||
|
expect(params.order_by).toEqual([])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('keeps an explicit user sort while searching so the user sort is respected', async () => {
|
||||||
|
await mountTaskList({s: 'find me', sort: 'title:asc'})
|
||||||
|
|
||||||
|
const params = lastRequestParams()
|
||||||
|
expect(params.s).toBe('find me')
|
||||||
|
expect(params.sort_by).toEqual(['title'])
|
||||||
|
expect(params.order_by).toEqual(['asc'])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('sends the default sort when not searching', async () => {
|
||||||
|
await mountTaskList({})
|
||||||
|
|
||||||
|
const params = lastRequestParams()
|
||||||
|
expect(params.s).toBe('')
|
||||||
|
expect(params.sort_by).not.toHaveLength(0)
|
||||||
|
// id always sorts last so other sort columns take precedence.
|
||||||
|
expect(params.sort_by).toEqual(['id'])
|
||||||
|
expect(params.order_by).toEqual(['desc'])
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
@ -122,6 +122,14 @@ export function useTaskList(
|
||||||
const allParams = computed(() => {
|
const allParams = computed(() => {
|
||||||
const loadParams = {...params.value}
|
const loadParams = {...params.value}
|
||||||
|
|
||||||
|
// Relevance ranking only engages when no sort is sent, so omit the default
|
||||||
|
// sort while searching and let an explicit user sort still take precedence.
|
||||||
|
if (loadParams.s && !sortQuery.value) {
|
||||||
|
loadParams.sort_by = []
|
||||||
|
loadParams.order_by = []
|
||||||
|
return loadParams
|
||||||
|
}
|
||||||
|
|
||||||
return formatSortOrder(sortBy.value, loadParams)
|
return formatSortOrder(sortBy.value, loadParams)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue