mirror of
https://github.com/hcengineering/platform.git
synced 2025-04-28 11:17:16 +00:00
Index attributes of AttachedTo object with elastic (#628)
Signed-off-by: Denis Bykhov <80476319+BykhovDenis@users.noreply.github.com>
This commit is contained in:
parent
556399f2e1
commit
d340b55af8
@ -14,7 +14,19 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
import core, { Hierarchy, AnyAttribute, Storage, DocumentQuery, FindOptions, FindResult, TxProcessor, TxMixin, TxPutBag, TxRemoveDoc } from '@anticrm/core'
|
import core, {
|
||||||
|
Hierarchy,
|
||||||
|
AnyAttribute,
|
||||||
|
Storage,
|
||||||
|
DocumentQuery,
|
||||||
|
FindOptions,
|
||||||
|
FindResult,
|
||||||
|
TxProcessor,
|
||||||
|
TxMixin,
|
||||||
|
TxPutBag,
|
||||||
|
TxRemoveDoc,
|
||||||
|
Collection
|
||||||
|
} from '@anticrm/core'
|
||||||
import type { AttachedDoc, TxUpdateDoc, TxCreateDoc, Doc, Ref, Class, Obj, TxResult } from '@anticrm/core'
|
import type { AttachedDoc, TxUpdateDoc, TxCreateDoc, Doc, Ref, Class, Obj, TxResult } from '@anticrm/core'
|
||||||
|
|
||||||
import type { IndexedDoc, FullTextAdapter, WithFind } from './types'
|
import type { IndexedDoc, FullTextAdapter, WithFind } from './types'
|
||||||
@ -47,11 +59,21 @@ export class FullTextIndex extends TxProcessor implements Storage {
|
|||||||
throw new Error('Method not implemented.')
|
throw new Error('Method not implemented.')
|
||||||
}
|
}
|
||||||
|
|
||||||
async findAll<T extends Doc> (_class: Ref<Class<T>>, query: DocumentQuery<T>, options?: FindOptions<T>): Promise<FindResult<T>> {
|
async findAll<T extends Doc>(
|
||||||
|
_class: Ref<Class<T>>,
|
||||||
|
query: DocumentQuery<T>,
|
||||||
|
options?: FindOptions<T>
|
||||||
|
): Promise<FindResult<T>> {
|
||||||
console.log('search', query)
|
console.log('search', query)
|
||||||
const docs = await this.adapter.search(query)
|
const docs = await this.adapter.search(query)
|
||||||
console.log(docs)
|
console.log(docs)
|
||||||
const ids = docs.map(doc => (doc.attachedTo ?? doc.id) as Ref<T>)
|
const ids: Ref<Doc>[] = []
|
||||||
|
for (const doc of docs) {
|
||||||
|
ids.push(doc.id)
|
||||||
|
if (doc.attachedTo !== undefined) {
|
||||||
|
ids.push(doc.attachedTo)
|
||||||
|
}
|
||||||
|
}
|
||||||
return await this.dbStorage.findAll(_class, { _id: { $in: ids as any } }, options) // TODO: remove `as any`
|
return await this.dbStorage.findAll(_class, { _id: { $in: ids as any } }, options) // TODO: remove `as any`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,9 +100,21 @@ export class FullTextIndex extends TxProcessor implements Storage {
|
|||||||
|
|
||||||
protected override async txCreateDoc (tx: TxCreateDoc<Doc>): Promise<TxResult> {
|
protected override async txCreateDoc (tx: TxCreateDoc<Doc>): Promise<TxResult> {
|
||||||
const attributes = this.getFullTextAttributes(tx.objectClass)
|
const attributes = this.getFullTextAttributes(tx.objectClass)
|
||||||
if (attributes === undefined) return {}
|
|
||||||
const doc = TxProcessor.createDoc2Doc(tx)
|
const doc = TxProcessor.createDoc2Doc(tx)
|
||||||
const content = attributes.map(attr => ((doc as any)[attr.name] !== null && (doc as any)[attr.name] !== undefined) ? (doc as any)[attr.name].toString() : '') // temporary: getFullTextAttributes should provide string attrs only
|
let parentContent: any[] = []
|
||||||
|
if (this.hierarchy.isDerived(doc._class, core.class.AttachedDoc)) {
|
||||||
|
const attachedDoc = doc as AttachedDoc
|
||||||
|
const parentDoc = (
|
||||||
|
await this.dbStorage.findAll(attachedDoc.attachedToClass, { _id: attachedDoc.attachedTo }, { limit: 1 })
|
||||||
|
)[0]
|
||||||
|
if (parentDoc !== undefined) {
|
||||||
|
const parentAttributes = this.getFullTextAttributes(parentDoc._class)
|
||||||
|
parentContent = this.getContent(parentAttributes, parentDoc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (attributes === undefined && parentContent.length === 0) return {}
|
||||||
|
let content = this.getContent(attributes, doc)
|
||||||
|
content = content.concat(parentContent)
|
||||||
const indexedDoc: IndexedDoc = {
|
const indexedDoc: IndexedDoc = {
|
||||||
id: doc._id,
|
id: doc._id,
|
||||||
_class: doc._class,
|
_class: doc._class,
|
||||||
@ -104,7 +138,8 @@ export class FullTextIndex extends TxProcessor implements Storage {
|
|||||||
|
|
||||||
protected override async txUpdateDoc (tx: TxUpdateDoc<Doc>): Promise<TxResult> {
|
protected override async txUpdateDoc (tx: TxUpdateDoc<Doc>): Promise<TxResult> {
|
||||||
const attributes = this.getFullTextAttributes(tx.objectClass)
|
const attributes = this.getFullTextAttributes(tx.objectClass)
|
||||||
if (attributes === undefined) return {}
|
let result = {}
|
||||||
|
if (attributes === undefined) return result
|
||||||
const ops: any = tx.operations
|
const ops: any = tx.operations
|
||||||
const update: any = {}
|
const update: any = {}
|
||||||
let i = 0
|
let i = 0
|
||||||
@ -117,8 +152,39 @@ export class FullTextIndex extends TxProcessor implements Storage {
|
|||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
if (shouldUpdate) {
|
if (shouldUpdate) {
|
||||||
return await this.adapter.update(tx.objectId, update)
|
result = await this.adapter.update(tx.objectId, update)
|
||||||
|
await this.updateAttachedDocs(tx, update)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
private getContent (attributes: AnyAttribute[] | undefined, doc: Doc): any[] {
|
||||||
|
if (attributes === undefined) return []
|
||||||
|
return attributes.map((attr) =>
|
||||||
|
(doc as any)[attr.name]?.toString() ?? ''
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private async updateAttachedDocs (tx: TxUpdateDoc<Doc>, update: any): Promise<void> {
|
||||||
|
const doc = (await this.dbStorage.findAll(tx.objectClass, { _id: tx.objectId }, { limit: 1 }))[0]
|
||||||
|
if (doc === undefined) return
|
||||||
|
const attributes = this.hierarchy.getAllAttributes(doc._class)
|
||||||
|
for (const attribute of attributes.values()) {
|
||||||
|
if (this.hierarchy.isDerived(attribute.type._class, core.class.Collection)) {
|
||||||
|
const collection = attribute.type as Collection<AttachedDoc>
|
||||||
|
const allAttached = await this.dbStorage.findAll(collection.of, { attachedTo: tx.objectId })
|
||||||
|
if (allAttached.length === 0) continue
|
||||||
|
const attributes = this.getFullTextAttributes(tx.objectClass)
|
||||||
|
const shift = attributes?.length ?? 0
|
||||||
|
const docUpdate: any = {}
|
||||||
|
for (const key in update) {
|
||||||
|
const index = Number.parseInt(key.replace('content', ''))
|
||||||
|
docUpdate[`content${index + shift}`] = update[key]
|
||||||
|
}
|
||||||
|
for (const attached of allAttached) {
|
||||||
|
await this.adapter.update(attached._id, docUpdate)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ export interface Trigger extends Doc {
|
|||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
export interface IndexedDoc {
|
export interface IndexedDoc {
|
||||||
id: string
|
id: Ref<Doc>
|
||||||
_class: Ref<Class<Doc>>
|
_class: Ref<Class<Doc>>
|
||||||
space: Ref<Space>
|
space: Ref<Space>
|
||||||
modifiedOn: Timestamp
|
modifiedOn: Timestamp
|
||||||
|
@ -178,7 +178,7 @@ export function start (config: { transactorEndpoint: string, elasticUrl: string,
|
|||||||
const elastic = await createElasticAdapter(config.elasticUrl, payload.workspace)
|
const elastic = await createElasticAdapter(config.elasticUrl, payload.workspace)
|
||||||
|
|
||||||
const indexedDoc: IndexedDoc = {
|
const indexedDoc: IndexedDoc = {
|
||||||
id: generateId() + '/attachments/' + name,
|
id: generateId() + '/attachments/' + name as Ref<Doc>,
|
||||||
_class: attachment.class.Attachment,
|
_class: attachment.class.Attachment,
|
||||||
space,
|
space,
|
||||||
modifiedOn: Date.now(),
|
modifiedOn: Date.now(),
|
||||||
@ -249,7 +249,7 @@ export function start (config: { transactorEndpoint: string, elasticUrl: string,
|
|||||||
const elastic = await createElasticAdapter(config.elasticUrl, payload.workspace)
|
const elastic = await createElasticAdapter(config.elasticUrl, payload.workspace)
|
||||||
|
|
||||||
const indexedDoc: IndexedDoc = {
|
const indexedDoc: IndexedDoc = {
|
||||||
id: generateId() + '/attachments/' + 'Profile.pdf',
|
id: generateId() + '/attachments/' + 'Profile.pdf' as Ref<Doc>,
|
||||||
_class: attachment.class.Attachment,
|
_class: attachment.class.Attachment,
|
||||||
space,
|
space,
|
||||||
modifiedOn: Date.now(),
|
modifiedOn: Date.now(),
|
||||||
|
Loading…
Reference in New Issue
Block a user