diff --git a/packages/core/src/classes.ts b/packages/core/src/classes.ts index 60f430c3d5..5d05086a27 100644 --- a/packages/core/src/classes.ts +++ b/packages/core/src/classes.ts @@ -94,7 +94,15 @@ export interface Type extends UXObject {} * @public */ export enum IndexKind { + /** + * Attribute with this index annotation should be added to elastic for search + * Could be added to string or Ref attribute + * TODO: rename properly for better code readability + */ FullText, + /** + * For attribute with this annotation should be created an index in mongo database + */ Indexed } diff --git a/server/core/src/indexer/fulltextPush.ts b/server/core/src/indexer/fulltextPush.ts index 7fe34280fe..6dbefa021a 100644 --- a/server/core/src/indexer/fulltextPush.ts +++ b/server/core/src/indexer/fulltextPush.ts @@ -14,12 +14,15 @@ // import core, { + AnyAttribute, + ArrOf, Class, Doc, DocIndexState, DocumentQuery, DocumentUpdate, extractDocKey, + IndexKind, MeasureContext, Ref, ServerStorage, @@ -95,6 +98,43 @@ export class FullTextPushStage implements FullTextPipelineStage { return { docs: [], pass: true } } + async indexRefAttributes ( + attributes: Map, + doc: DocIndexState, + elasticDoc: IndexedDoc, + metrics: MeasureContext + ): Promise { + for (const attribute in doc.attributes) { + const { attr } = extractDocKey(attribute) + const attrObj = attributes.get(attr) + if ( + attrObj !== null && + attrObj !== undefined && + attrObj.index === IndexKind.FullText && + (attrObj.type._class === core.class.RefTo || + (attrObj.type._class === core.class.ArrOf && (attrObj.type as ArrOf).of._class === core.class.RefTo)) + ) { + const attrStringValue = doc.attributes[attribute] + if (attrStringValue !== undefined && attrStringValue !== null && attrStringValue !== '') { + const refs = attrStringValue.split(',') + const refDocs = await metrics.with( + 'ref-docs', + {}, + async (ctx) => + await this.dbStorage.findAll(ctx, core.class.DocIndexState, { + _id: { $in: refs } + }) + ) + if (refDocs.length > 0) { + refDocs.forEach((c) => { + updateDoc2Elastic(c.attributes, elasticDoc, c._id) + }) + } + } + } + } + } + async collect (toIndex: DocIndexState[], pipeline: FullTextPipeline, metrics: MeasureContext): Promise { const bulk: IndexedDoc[] = [] @@ -162,6 +202,11 @@ export class FullTextPushStage implements FullTextPipelineStage { } } + const allAttributes = pipeline.hierarchy.getAllAttributes(elasticDoc._class) + + // Include child ref attributes + await this.indexRefAttributes(allAttributes, doc, elasticDoc, metrics) + this.checkIntegrity(elasticDoc) bulk.push(elasticDoc) } catch (err: any) { diff --git a/server/core/src/indexer/indexer.ts b/server/core/src/indexer/indexer.ts index 1f9ab9d2a5..cd0936a9ea 100644 --- a/server/core/src/indexer/indexer.ts +++ b/server/core/src/indexer/indexer.ts @@ -534,7 +534,7 @@ export class FullTextIndexPipeline implements FullTextPipeline { async checkIndexConsistency (dbStorage: ServerStorage): Promise { if (process.env.MODEL_VERSION !== undefined) { - const modelVersion = await (await this.model.findAll(core.class.Version, {})).shift() + const modelVersion = (await this.model.findAll(core.class.Version, {})).shift() if (modelVersion !== undefined) { const modelVersionString = versionToString(modelVersion) if (modelVersionString !== process.env.MODEL_VERSION) { diff --git a/server/core/src/indexer/types.ts b/server/core/src/indexer/types.ts index 82fca974ba..1763c61594 100644 --- a/server/core/src/indexer/types.ts +++ b/server/core/src/indexer/types.ts @@ -107,4 +107,4 @@ export const fieldStateId = 'fld-v5' /** * @public */ -export const fullTextPushStageId = 'fts-v4' +export const fullTextPushStageId = 'fts-v5'