Fix indexes, use DocIndexState for fields shown in search (#4341)

* fix indexes, rework to use DocIndexState

Signed-off-by: Vyacheslav Tumanov <me@slavatumanov.me>

* fix icons for issues

Signed-off-by: Vyacheslav Tumanov <me@slavatumanov.me>

* remove commented lines

Signed-off-by: Vyacheslav Tumanov <me@slavatumanov.me>

---------

Signed-off-by: Vyacheslav Tumanov <me@slavatumanov.me>
This commit is contained in:
Vyacheslav Tumanov 2024-01-13 13:56:43 +05:00 committed by GitHub
parent 5d2f274089
commit a1690d6c0f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 57 additions and 27 deletions

View File

@ -20,11 +20,11 @@
import IssueStatusIcon from './IssueStatusIcon.svelte'
export let status: string
export let space: Ref<Space>
export let status: string | string[]
export let space: Ref<Space> | Ref<Space>[]
$: st = $statusStore.byId.get(status as Ref<Status>)
$: spaceProject = space as Ref<Project>
$: st = $statusStore.byId.get(Array.isArray(status) ? (status[0] as Ref<Status>) : (status as Ref<Status>))
$: spaceProject = Array.isArray(space) ? (space[0] as Ref<Project>) : (space as Ref<Project>)
</script>
{#if st}

View File

@ -178,7 +178,7 @@ export class FullTextPushStage implements FullTextPipelineStage {
}
}
}
const parentDoc: DocIndexState | undefined = undefined
if (doc.attachedToClass != null && doc.attachedTo != null) {
const propagate: Ref<Class<Doc>>[] = collectPropagate(pipeline, doc.attachedToClass)
if (propagate.some((it) => pipeline.hierarchy.isDerived(doc.objectClass, it))) {
@ -210,13 +210,21 @@ export class FullTextPushStage implements FullTextPipelineStage {
}
}
}
const [spaceDoc] = await metrics.with(
'find-space',
{},
async (ctx) =>
await this.dbStorage.findAll(ctx, core.class.DocIndexState, {
_id: doc.space as any as Ref<DocIndexState>
})
)
const allAttributes = pipeline.hierarchy.getAllAttributes(elasticDoc._class)
// Include child ref attributes
await this.indexRefAttributes(allAttributes, doc, elasticDoc, metrics)
await updateDocWithPresenter(pipeline.hierarchy, elasticDoc)
await updateDocWithPresenter(pipeline.hierarchy, doc, elasticDoc, { parentDoc, spaceDoc })
this.checkIntegrity(elasticDoc)
bulk.push(elasticDoc)

View File

@ -107,4 +107,4 @@ export const fieldStateId = 'fld-v11'
/**
* @public
*/
export const fullTextPushStageId = 'fts-v7'
export const fullTextPushStageId = 'fts-v8'

View File

@ -1,8 +1,8 @@
import { Hierarchy, Ref, RefTo, Class, Doc, SearchResultDoc, docKey } from '@hcengineering/core'
import { Class, Doc, DocIndexState, docKey, Hierarchy, Ref, RefTo, SearchResultDoc } from '@hcengineering/core'
import { getResource } from '@hcengineering/platform'
import plugin from './plugin'
import { IndexedDoc, SearchPresenter, ClassSearchConfigProps, SearchScoring } from './types'
import { ClassSearchConfigProps, IndexedDoc, SearchPresenter, SearchScoring } from './types'
interface IndexedReader {
get: (attribute: string) => any
@ -13,22 +13,26 @@ interface IndexedReader {
function createIndexedReader (
_class: Ref<Class<Doc>>,
hierarchy: Hierarchy,
doc: IndexedDoc,
doc: DocIndexState,
otherDocs?: Record<string, DocIndexState | undefined>,
refAttribute?: string
): IndexedReader {
return {
get: (attr: string) => {
const realAttr = hierarchy.findAttribute(_class, attr)
if (realAttr !== undefined) {
return doc[docKey(attr, { refAttribute, _class: realAttr.attributeOf })]
return doc.attributes[docKey(attr, { refAttribute, _class: realAttr.attributeOf })]
}
return undefined
},
getDoc: (attr: string) => {
const realAttr = hierarchy.findAttribute(_class, attr)
if (realAttr !== undefined) {
const refAtrr = realAttr.type as RefTo<Doc>
return createIndexedReader(refAtrr.to, hierarchy, doc, docKey(attr, { _class }))
const anotherDoc = otherDocs?.[attr]
if (anotherDoc !== undefined) {
const refAtrr = realAttr.type as RefTo<Doc>
return createIndexedReader(refAtrr.to, hierarchy, anotherDoc, otherDocs, docKey(attr, { _class }))
}
}
return undefined
}
@ -66,13 +70,24 @@ function findSearchPresenter (hierarchy: Hierarchy, _class: Ref<Class<Doc>>): Se
/**
* @public
*/
export async function updateDocWithPresenter (hierarchy: Hierarchy, doc: IndexedDoc): Promise<void> {
const searchPresenter = findSearchPresenter(hierarchy, doc._class)
export async function updateDocWithPresenter (
hierarchy: Hierarchy,
doc: DocIndexState,
elasticDoc: IndexedDoc,
refDocs: {
parentDoc: DocIndexState | undefined
spaceDoc: DocIndexState | undefined
}
): Promise<void> {
const searchPresenter = findSearchPresenter(hierarchy, elasticDoc._class)
if (searchPresenter === undefined) {
return
}
const reader = createIndexedReader(doc._class, hierarchy, doc)
const reader = createIndexedReader(elasticDoc._class, hierarchy, doc, {
space: refDocs.spaceDoc,
attachedTo: refDocs.parentDoc
})
const props = [
{
@ -80,7 +95,7 @@ export async function updateDocWithPresenter (hierarchy: Hierarchy, doc: Indexed
config: searchPresenter.searchConfig.title,
provider: searchPresenter.getSearchTitle
}
]
] as any[]
if (searchPresenter.searchConfig.shortTitle !== undefined) {
props.push({
@ -90,20 +105,29 @@ export async function updateDocWithPresenter (hierarchy: Hierarchy, doc: Indexed
})
}
if (searchPresenter.searchConfig.iconConfig !== undefined) {
props.push({
name: 'searchIcon',
config: searchPresenter.searchConfig.iconConfig
})
}
for (const prop of props) {
let value
if (typeof prop.config === 'string') {
value = reader.get(prop.config)
} else if (prop.config.tmpl !== undefined) {
if (prop.config.tmpl !== undefined) {
const tmpl = prop.config.tmpl
const renderProps = readAndMapProps(reader, prop.config.props)
value = fillTemplate(tmpl, renderProps)
} else if (typeof prop.config === 'string') {
value = reader.get(prop.config)
} else if (prop.provider !== undefined) {
const func = await getResource(prop.provider)
const func = (await getResource(prop.provider)) as any
const renderProps = readAndMapProps(reader, prop.config.props)
value = func(hierarchy, { _class: doc._class, ...renderProps })
value = func(hierarchy, { _class: elasticDoc._class, ...renderProps })
} else if (prop.name === 'searchIcon') {
value = readAndMapProps(reader, prop.config.props)
}
doc[prop.name] = value
elasticDoc[prop.name] = value
}
}
@ -126,6 +150,7 @@ export function mapSearchResultDoc (hierarchy: Hierarchy, raw: IndexedDoc): Sear
id: raw.id,
title: raw.searchTitle,
shortTitle: raw.searchShortTitle,
iconProps: raw.searchIcon,
doc: {
_id: raw.id,
_class: raw._class
@ -138,10 +163,6 @@ export function mapSearchResultDoc (hierarchy: Hierarchy, raw: IndexedDoc): Sear
}
if (searchPresenter?.searchConfig.iconConfig !== undefined) {
doc.iconComponent = searchPresenter.searchConfig.iconConfig.component
doc.iconProps = readAndMapProps(
createIndexedReader(raw._class, hierarchy, raw),
searchPresenter.searchConfig.iconConfig.props
)
}
return doc

View File

@ -165,6 +165,7 @@ export interface IndexedDoc {
attachedToClass?: Ref<Class<Doc>>
searchTitle?: string
searchShortTitle?: string
searchIcon?: any
[key: string]: any
}