diff --git a/models/core/src/core.ts b/models/core/src/core.ts index a4ed6d1b85..889a5ea221 100644 --- a/models/core/src/core.ts +++ b/models/core/src/core.ts @@ -13,44 +13,37 @@ // limitations under the License. // -import type { IntlString } from '@anticrm/platform' -import type { +import { Account, - AnyAttribute, - AttachedDoc, + AnyAttribute, ArrOf, AttachedDoc, Class, - ClassifierKind, - Doc, - Domain, - Mixin, + ClassifierKind, Collection, Doc, + Domain, DOMAIN_MODEL, IndexKind, Interface, Mixin, Obj, - Ref, - Space, + Ref, RefTo, Space, Timestamp, - Type, - Collection, - RefTo, - ArrOf, - Interface, - Version + Type, Version } from '@anticrm/core' -import { DOMAIN_MODEL } from '@anticrm/core' -import { Model, Prop, TypeRef, TypeString, TypeTimestamp } from '@anticrm/model' +import { Index, Model, Prop, TypeRef, TypeString, TypeTimestamp } from '@anticrm/model' +import type { IntlString } from '@anticrm/platform' import core from './component' // C O R E @Model(core.class.Obj, core.class.Obj) export class TObj implements Obj { @Prop(TypeRef(core.class.Class), 'Class' as IntlString) + @Index(IndexKind.Indexed) _class!: Ref<Class<this>> } @Model(core.class.Doc, core.class.Obj) export class TDoc extends TObj implements Doc { @Prop(TypeRef(core.class.Doc), 'Id' as IntlString) + // @Index(IndexKind.Indexed) // - automatically indexed by default. _id!: Ref<this> @Prop(TypeRef(core.class.Space), 'Space' as IntlString) + @Index(IndexKind.Indexed) space!: Ref<Space> @Prop(TypeTimestamp(), 'Modified' as IntlString) @@ -63,9 +56,11 @@ export class TDoc extends TObj implements Doc { @Model(core.class.AttachedDoc, core.class.Doc) export class TAttachedDoc extends TDoc implements AttachedDoc { @Prop(TypeRef(core.class.Doc), 'Attached to' as IntlString) + @Index(IndexKind.Indexed) attachedTo!: Ref<Doc> @Prop(TypeRef(core.class.Class), 'Attached to class' as IntlString) + @Index(IndexKind.Indexed) attachedToClass!: Ref<Class<Doc>> @Prop(TypeString(), 'Collection' as IntlString) diff --git a/packages/core/src/classes.ts b/packages/core/src/classes.ts index 194876dce1..0626f6d748 100644 --- a/packages/core/src/classes.ts +++ b/packages/core/src/classes.ts @@ -81,7 +81,8 @@ export interface Type<T extends PropertyType> extends UXObject {} * @public */ export enum IndexKind { - FullText + FullText, + Indexed } /** diff --git a/server/tool/src/index.ts b/server/tool/src/index.ts index fa9abf111c..66b52f34bd 100644 --- a/server/tool/src/index.ts +++ b/server/tool/src/index.ts @@ -14,10 +14,10 @@ // import contact from '@anticrm/contact' -import core, { DOMAIN_TX, Tx } from '@anticrm/core' +import core, { DOMAIN_TX, Tx, Client as CoreClient, Domain, IndexKind, DOMAIN_MODEL } from '@anticrm/core' import builder, { createDeps, migrateOperations } from '@anticrm/model-all' import { Client } from 'minio' -import { Document, MongoClient } from 'mongodb' +import { Db, Document, MongoClient } from 'mongodb' import { connect } from './connect' import toolPlugin from './plugin' import { MigrateClientImpl } from './upgrade' @@ -106,6 +106,9 @@ export async function initModel (transactorUrl: string, dbName: string): Promise await connection.close() } + // Create update indexes + await createUpdateIndexes(connection, db) + console.log('create minio bucket') if (!(await minio.bucketExists(dbName))) { await minio.makeBucket(dbName, 'k8s') @@ -154,6 +157,10 @@ export async function upgradeModel ( console.log('Apply upgrade operations') const connection = await connect(transactorUrl, dbName, true) + + // Create update indexes + await createUpdateIndexes(connection, db) + for (const op of migrateOperations) { await op.upgrade(connection) } @@ -163,3 +170,38 @@ export async function upgradeModel ( await client.close() } } + +async function createUpdateIndexes (connection: CoreClient, db: Db): Promise<void> { + const classes = await connection.findAll(core.class.Class, {}) + + const hierarchy = connection.getHierarchy() + const domains = new Map<Domain, Set<string>>() + // Find all domains and indexed fields inside + for (const c of classes) { + try { + const domain = hierarchy.getDomain(c._id) + if (domain === DOMAIN_MODEL) { + continue + } + const attrs = hierarchy.getAllAttributes(c._id) + const domainAttrs = domains.get(domain) ?? new Set<string>() + for (const a of attrs.values()) { + if (a.index !== undefined && a.index === IndexKind.Indexed) { + domainAttrs.add(a.name) + } + } + + domains.set(domain, domainAttrs) + } catch (err: any) { + // Ignore, since we have clases without domain. + } + } + + for (const [d, v] of domains.entries()) { + const collection = db.collection(d) + for (const vv of v.values()) { + console.log('creating index', d, vv) + await collection.createIndex(vv) + } + } +}