From cfbefe9fef19e18c1c8ba18a42786dc4b4513d94 Mon Sep 17 00:00:00 2001 From: Andrey Sobolev Date: Sat, 12 Feb 2022 01:12:12 +0700 Subject: [PATCH] Create indexes for most used fields Create indexes for most used fields Closes #995 Signed-off-by: Andrey Sobolev --- models/core/src/core.ts | 31 ++++++++++-------------- packages/core/src/classes.ts | 3 ++- server/tool/src/index.ts | 46 ++++++++++++++++++++++++++++++++++-- 3 files changed, 59 insertions(+), 21 deletions(-) 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> } @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 @Prop(TypeRef(core.class.Space), 'Space' as IntlString) + @Index(IndexKind.Indexed) space!: Ref @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 @Prop(TypeRef(core.class.Class), 'Attached to class' as IntlString) + @Index(IndexKind.Indexed) attachedToClass!: Ref> @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 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 { + const classes = await connection.findAll(core.class.Class, {}) + + const hierarchy = connection.getHierarchy() + const domains = new Map>() + // 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() + 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) + } + } +}