Skip to content

feat(web&sdk): add index manage #1611

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Oct 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion packages/database-proxy/src/accessor/accessor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,21 @@ export interface CountResult {
total: number
}

export interface CreateIndexResult {
indexName: string
}

export interface DropIndexResult {
result: any
}

export interface ListIndexesResult {
list: object[]
}

export interface AccessorInterface {
type: string,
execute(params: Params): Promise<ReadResult | UpdateResult | AddResult | RemoveResult | CountResult>
execute(params: Params): Promise<ReadResult | UpdateResult | AddResult | RemoveResult | CountResult | CreateIndexResult | DropIndexResult | ListIndexesResult>
get(collection: string, query: any): Promise<any>
close(): void
on(event: string | symbol, listener: (...args: any[]) => void): void
Expand Down
122 changes: 98 additions & 24 deletions packages/database-proxy/src/accessor/mongo.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { AccessorInterface, ReadResult, UpdateResult, AddResult, RemoveResult, CountResult } from "./accessor"
import { AccessorInterface, ReadResult, UpdateResult, AddResult, RemoveResult, CountResult, ListIndexesResult, DropIndexResult, CreateIndexResult } from "./accessor"
import { Params, ActionType, Order, Direction } from '../types'
import { MongoClient, ObjectId, MongoClientOptions, Db, UpdateOptions, Filter } from 'mongodb'
import * as mongodb from 'mongodb'
Expand Down Expand Up @@ -141,33 +141,32 @@ export class MongoAccessor implements AccessorInterface {
* @param params 数据请求参数
* @returns
*/
async execute(params: Params): Promise<ReadResult | UpdateResult | AddResult | RemoveResult | CountResult | never> {
async execute(params: Params): Promise<ReadResult | UpdateResult | AddResult | RemoveResult | CountResult | CreateIndexResult | DropIndexResult | ListIndexesResult | never> {
const { collection, action } = params

this.logger.info(`mongo start executing {${collection}}: ` + JSON.stringify(params))

if (action === ActionType.READ) {
return await this.read(collection, params)
}

if (action === ActionType.AGGREGATE) {
return await this.aggregate(collection, params)
}

if (action === ActionType.UPDATE) {
return await this.update(collection, params)
}

if (action === ActionType.ADD) {
return await this.add(collection, params)
}

if (action === ActionType.REMOVE) {
return await this.remove(collection, params)
}

if (action === ActionType.COUNT) {
return await this.count(collection, params)
switch (action) {
case ActionType.READ:
return await this.read(collection, params)
case ActionType.UPDATE:
return await this.update(collection, params)
case ActionType.AGGREGATE:
return await this.aggregate(collection, params)
case ActionType.REMOVE:
return await this.remove(collection, params)
case ActionType.ADD:
return await this.add(collection, params)
case ActionType.COUNT:
return await this.count(collection, params)
case ActionType.CREATE_INDEX:
return await this.createIndex(collection, params)
case ActionType.CREATE_INDEX:
return await this.createIndex(collection, params)
case ActionType.DROP_INDEX:
return await this.dropIndex(collection, params)
case ActionType.LIST_INDEXES:
return await this.listIndexes(collection, params)
}

const error = new Error(`invalid 'action': ${action}`)
Expand Down Expand Up @@ -446,4 +445,79 @@ export class MongoAccessor implements AccessorInterface {
})
return _stages
}

/**
* Execute create index query
* @param collection Collection name
* @param params
* @returns
*/
protected async createIndex(collection: string, params: Params): Promise<CreateIndexResult> {
const coll = this.db.collection(collection)
let { data } = params
data = this.deserializedEjson(data || {})

const { keys, options } = data;

this.logger.debug(`mongo before creating index {${collection}}: `, { data })

const result = await coll.createIndex(
keys as mongodb.IndexSpecification,
options as mongodb.CreateIndexesOptions
)

const ret: CreateIndexResult = {
indexName: result
}

this.emitResult(params, ret)
this.logger.debug(`mongo end of creating index {${collection}}: `, { data, result: ret })
return ret
}

/**
* Execute drop index query
* @param collection Collection name
* @param params
* @returns
*/
protected async dropIndex(collection: string, params: Params): Promise<DropIndexResult> {
const coll = this.db.collection(collection)
let { data } = params
data = this.deserializedEjson(data || {})

this.logger.debug(`mongo before drop index {${collection}}: `, { data })

const result = await coll.dropIndex(data)

const ret: DropIndexResult = {
result
}

this.emitResult(params, ret)
this.logger.debug(`mongo end of drop index {${collection}}: `, { data, result: ret })
return ret
}

/**
* Execute list indexes query
* @param collection Collection name
* @param params
* @returns
*/
protected async listIndexes(collection: string, params: Params): Promise<ListIndexesResult> {
const coll = this.db.collection(collection)
let { data } = params
data = this.deserializedEjson(data || {})

this.logger.debug(`mongo before listing indexes {${collection}}: `, { data })

const result = await coll.listIndexes(data).toArray()

this.logger.debug(`mongo end of listing indexes {${collection}}: `, { data })

this.emitResult(params, { result })
const serialized = result.map(doc => this.serializeBson(doc))
return { list: serialized }
}
}
28 changes: 26 additions & 2 deletions packages/database-proxy/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@ export enum ActionType {
REMOVE = 'database.deleteDocument',
COUNT = 'database.countDocument',
WATCH = 'database.watchDocument',
AGGREGATE = 'database.aggregateDocuments'
AGGREGATE = 'database.aggregateDocuments',
CREATE_INDEX = 'database.createIndex',
CREATE_INDEXES = "database.createIndexes",
DROP_INDEX = "database.dropIndex",
DROP_INDEXES = "database.dropIndexes",
LIST_INDEXES = "database.listIndexes",
}

export interface Action {
Expand Down Expand Up @@ -78,6 +83,10 @@ const AddAcceptParams = ['data', 'multi']
const RemoveAcceptParams = ['query', 'multi', 'joins']
const CountAcceptParams = ['query', 'joins']
const AggregateAcceptParams = ['stages']
const CreateIndexParams = ['data']
const DropIndexParams = ['data']
const DropIndexesParams = ['data']
const ListIndexesParams = ['data']

const ReadAction: Action = { type: ActionType.READ, fields: ReadAcceptParams }
const UpdateAction: Action = { type: ActionType.UPDATE, fields: UpdateAcceptParams }
Expand All @@ -86,9 +95,12 @@ const AddAction: Action = { type: ActionType.ADD, fields: AddAcceptParams }
const CountAction: Action = { type: ActionType.COUNT, fields: CountAcceptParams }
const WatchAction: Action = { type: ActionType.WATCH, fields: ReadAcceptParams }
const AggregateAction: Action = { type: ActionType.AGGREGATE, fields: AggregateAcceptParams }
const CreateIndexAction: Action = { type: ActionType.CREATE_INDEX, fields: CreateIndexParams }
const DropIndexAction: Action = { type: ActionType.DROP_INDEX, fields: DropIndexParams }
const DropIndexesAction: Action = { type: ActionType.DROP_INDEXES, fields:DropIndexesParams }
const ListIndexesAction: Action = { type: ActionType.LIST_INDEXES, fields: ListIndexesParams }

export function getAction(actionName: ActionType): Action | null {

let action: Action
switch (actionName) {
case ActionType.READ:
Expand All @@ -112,6 +124,18 @@ export function getAction(actionName: ActionType): Action | null {
case ActionType.AGGREGATE:
action = AggregateAction
break
case ActionType.CREATE_INDEX:
action = CreateIndexAction
break
case ActionType.DROP_INDEX:
action = DropIndexAction
break
case ActionType.DROP_INDEXES:
action = DropIndexesAction
break
case ActionType.LIST_INDEXES:
action = ListIndexesAction
break
default:
action = null
}
Expand Down
22 changes: 22 additions & 0 deletions packages/database-ql/src/collection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Db } from './index'
import { DocumentReference } from './document'
import { Query } from './query'
import Aggregation from './aggregate'
import { CreateIndexRes, DropIndexRes, ListIndexesRes } from './result-types'


/**
Expand Down Expand Up @@ -53,4 +54,25 @@ export class CollectionReference extends Query {
aggregate(rawPipeline: object[] = []) {
return new Aggregation(this._db, this._coll, rawPipeline)
}

/**
* 创建索引
*/
public async createIndex(keys: Record<string, number | string>, options?: any): Promise<CreateIndexRes> {
let docRef = new DocumentReference(this._db, this._coll, undefined)
return docRef.createIndex(keys, options)
}

/**
* 删除索引
*/
public async dropIndex(index: string | Record<string, number | string>): Promise<DropIndexRes> {
let docRef = new DocumentReference(this._db, this._coll, undefined)
return docRef.dropIndex(index)
}

public async listIndexes(): Promise<ListIndexesRes> {
let docRef = new DocumentReference(this._db, this._coll, undefined)
return docRef.listIndexes()
}
}
5 changes: 4 additions & 1 deletion packages/database-ql/src/constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,10 @@ enum ActionType {
update = 'database.updateDocument',
count = 'database.countDocument',
remove = 'database.deleteDocument',
aggregate = 'database.aggregateDocuments'
aggregate = 'database.aggregateDocuments',
createIndex = 'database.createIndex',
dropIndex = "database.dropIndex",
listIndexes = "database.listIndexes",
}

export {
Expand Down
95 changes: 94 additions & 1 deletion packages/database-ql/src/document.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Db } from './index'
import { serialize } from './serializer/datatype'
import { UpdateCommand } from './commands/update'
import { ActionType } from './constant'
import { AddRes, GetOneRes, RemoveRes, UpdateRes } from './result-types'
import { AddRes, CreateIndexRes, DropIndexRes, GetOneRes, ListIndexesRes, RemoveRes, UpdateRes } from './result-types'
import { ProjectionType } from './interface'
import { Query } from './query'

Expand Down Expand Up @@ -165,4 +165,97 @@ export class DocumentReference {
field(projection: string[] | ProjectionType): DocumentReference {
return new DocumentReference(this._db, this._coll, this.id, this._query.field(projection))
}


/**
* 创建索引
*
* @param data - document data
*/
async createIndex(keys: object, options?: object): Promise<CreateIndexRes> {
if (typeof keys !== 'object' || Object.keys(keys)?.length === 0) {
throw new Error('keys cannot be empty object')
}

const data = {
keys,
options
}

const params = {
collectionName: this._coll,
data: serialize(data),
}

const res = await this._query
.send(ActionType.createIndex, params)

if (res.error) {
return {
requestId: res.requestId,
error: res.error,
ok: false,
code: res.code,
indexName: null,
}
}

return {
requestId: res.requestId,
ok: true,
indexName: res.data.indexName,
}
}

async dropIndex(index: string | object): Promise<DropIndexRes> {
const params = {
collectionName: this._coll,
data: serialize(index),
}

const res = await this._query
.send(ActionType.dropIndex, params)

if (res.error) {
return {
requestId: res.requestId,
error: res.error,
ok: false,
code: res.code,
result: null,
}
}

return {
requestId: res.requestId,
ok: true,
result: res.data.result,
}
}

async listIndexes(options?: object): Promise<ListIndexesRes> {
const params = {
collectionName: this._coll,
data: serialize(options),
}

const res = await this._query
.send(ActionType.listIndexes, params)

if (res.error) {
return {
requestId: res.requestId,
error: res.error,
ok: false,
code: res.code,
list: res.data.list
}
}

return {
requestId: res.requestId,
ok: true,
list: res.data.list,
}
}
}
2 changes: 1 addition & 1 deletion packages/database-ql/src/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { ActionType, OrderByDirection } from "./constant"
export interface ResponseStruct {
code: number
data: any
error: string
error: any
requestId: string
[extra: string]: any
}
Expand Down
2 changes: 1 addition & 1 deletion packages/database-ql/src/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Validate } from './validate'
import { QuerySerializer } from './serializer/query'
import { UpdateSerializer } from './serializer/update'
import { ErrorCode } from './constant'
import { GetOneRes, GetRes, CountRes, UpdateRes, RemoveRes } from './result-types'
import { GetOneRes, GetRes, CountRes, UpdateRes, RemoveRes} from './result-types'
import { ProjectionType, QueryOrder, RequestInterface, QueryParam } from './interface'
import { Util } from './util'
import { serialize } from './serializer/datatype'
Expand Down
Loading