mirror of
https://github.com/hcengineering/platform.git
synced 2025-04-14 20:39:03 +00:00
UBER-803: Fix slow filter (#3634)
Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
parent
97abd2fc12
commit
72c026d505
@ -224,14 +224,14 @@ export class LiveQuery {
|
||||
|
||||
const unsub = liveQuery.query(
|
||||
_class,
|
||||
piplineQuery.query ?? query,
|
||||
query,
|
||||
(result) => {
|
||||
// If we have one more request after this one, no need to do something.
|
||||
if (id === this.reqId) {
|
||||
callback(result)
|
||||
}
|
||||
},
|
||||
piplineQuery.options ?? options
|
||||
options
|
||||
)
|
||||
this.unsubscribe = () => {
|
||||
unsub()
|
||||
|
@ -17,7 +17,7 @@
|
||||
import type { DisplayTx, TxViewlet } from '@hcengineering/activity'
|
||||
import attachment from '@hcengineering/attachment'
|
||||
import chunter from '@hcengineering/chunter'
|
||||
import contact, { Employee, PersonAccount, getName } from '@hcengineering/contact'
|
||||
import contact, { Person, PersonAccount, getName } from '@hcengineering/contact'
|
||||
import core, { AnyAttribute, Class, Doc, Ref, TxCUD, getCurrentAccount } from '@hcengineering/core'
|
||||
import { Asset } from '@hcengineering/platform'
|
||||
import { createQuery, getClient } from '@hcengineering/presentation'
|
||||
@ -56,7 +56,7 @@
|
||||
let viewlet: TxDisplayViewlet | undefined
|
||||
let props: any
|
||||
let account: PersonAccount | undefined
|
||||
let employee: Employee | undefined
|
||||
let person: Person | undefined
|
||||
let model: AttributeModel[] = []
|
||||
let modelIcon: Asset | undefined = undefined
|
||||
let iconComponent: AnyComponent | undefined = undefined
|
||||
@ -67,7 +67,7 @@
|
||||
$: if (tx.tx._id !== ptx?.tx._id) {
|
||||
if (tx.tx.modifiedBy !== account?._id) {
|
||||
account = undefined
|
||||
employee = undefined
|
||||
person = undefined
|
||||
}
|
||||
viewlet = undefined
|
||||
props = undefined
|
||||
@ -107,10 +107,10 @@
|
||||
|
||||
$: account &&
|
||||
employeeQuery.query(
|
||||
contact.mixin.Employee,
|
||||
{ _id: account.person as Ref<Employee> },
|
||||
contact.class.Person,
|
||||
{ _id: account.person },
|
||||
(res) => {
|
||||
;[employee] = res
|
||||
;[person] = res
|
||||
},
|
||||
{ limit: 1 }
|
||||
)
|
||||
@ -191,7 +191,7 @@
|
||||
{#if showIcon}
|
||||
{#if withAvatar}
|
||||
<div class="msgactivity-avatar">
|
||||
<Component is={contact.component.Avatar} props={{ avatar: employee?.avatar, size: 'medium' }} />
|
||||
<Component is={contact.component.Avatar} props={{ avatar: person?.avatar, size: 'medium' }} />
|
||||
</div>
|
||||
{:else}
|
||||
<div class="msgactivity-icon">
|
||||
@ -212,8 +212,8 @@
|
||||
<div class="msgactivity-content__header">
|
||||
<div class="msgactivity-content__title labels-row">
|
||||
<span class={withAvatar ? 'bold' : 'strong'}>
|
||||
{#if employee}
|
||||
{getName(client.getHierarchy(), employee)}
|
||||
{#if person}
|
||||
{getName(client.getHierarchy(), person)}
|
||||
{:else}
|
||||
<Label label={core.string.System} />
|
||||
{/if}
|
||||
|
@ -96,8 +96,8 @@ export class AggregationMiddleware extends BasePresentationMiddleware implements
|
||||
const statusFields: Array<Attribute<Doc>> = []
|
||||
const allAttrs = h.getAllAttributes(_class)
|
||||
|
||||
const updatedQuery: DocumentQuery<T> = { ...(ret.query ?? query) }
|
||||
const finalOptions = { ...(ret.options ?? options ?? {}) }
|
||||
const updatedQuery: DocumentQuery<T> = h.clone(ret.query ?? query)
|
||||
const finalOptions = h.clone(ret.options ?? options ?? {})
|
||||
|
||||
await this.updateQueryOptions<T>(allAttrs, h, statusFields, updatedQuery, finalOptions)
|
||||
|
||||
@ -139,11 +139,13 @@ export class AggregationMiddleware extends BasePresentationMiddleware implements
|
||||
const docFields: Array<Attribute<Doc>> = []
|
||||
const h = this.client.getHierarchy()
|
||||
const allAttrs = h.getAllAttributes(_class)
|
||||
const finalOptions = options ?? {}
|
||||
const finalOptions = h.clone(options ?? {})
|
||||
|
||||
await this.updateQueryOptions<T>(allAttrs, h, docFields, query, finalOptions)
|
||||
const fquery = h.clone(query ?? {})
|
||||
|
||||
const result = await this.provideFindAll(_class, query, finalOptions)
|
||||
await this.updateQueryOptions<T>(allAttrs, h, docFields, fquery, finalOptions)
|
||||
|
||||
const result = await this.provideFindAll(_class, fquery, finalOptions)
|
||||
// We need to add $
|
||||
if (docFields.length > 0) {
|
||||
// We need to update $lookup for doc fields and provide $doc group fields.
|
||||
|
@ -24,16 +24,19 @@ import core, {
|
||||
DocumentQuery,
|
||||
FindOptions,
|
||||
Hierarchy,
|
||||
IdMap,
|
||||
Ref,
|
||||
SortingOrder,
|
||||
SortingRules,
|
||||
Space,
|
||||
Status,
|
||||
StatusCategory,
|
||||
StatusManager,
|
||||
StatusValue,
|
||||
Tx,
|
||||
WithLookup,
|
||||
matchQuery
|
||||
matchQuery,
|
||||
toIdMap
|
||||
} from '@hcengineering/core'
|
||||
import { LiveQuery } from '@hcengineering/query'
|
||||
import { AggregationManager, GrouppingManager } from '@hcengineering/view'
|
||||
@ -47,8 +50,15 @@ export const statusStore = writable<StatusManager>(new StatusManager([]))
|
||||
*/
|
||||
export class StatusAggregationManager implements AggregationManager {
|
||||
docs: Doc[] | undefined
|
||||
|
||||
docsByName: Map<string, Status[]> = new Map<string, Status[]>()
|
||||
mgr: StatusManager | Promise<StatusManager> | undefined
|
||||
statusCategory: IdMap<StatusCategory> = new Map()
|
||||
query: (() => void) | undefined
|
||||
|
||||
categoryQuery: (() => void) | undefined
|
||||
categoryPromise!: Promise<void>
|
||||
|
||||
lq: LiveQuery
|
||||
lqCallback: () => void
|
||||
|
||||
@ -68,14 +78,27 @@ export class StatusAggregationManager implements AggregationManager {
|
||||
}
|
||||
return this.mgr
|
||||
}
|
||||
this.categoryPromise = new Promise((resolve) => {
|
||||
this.categoryQuery = this.lq.query(core.class.StatusCategory, {}, (res) => {
|
||||
this.statusCategory = toIdMap(res)
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
this.mgr = new Promise<StatusManager>((resolve) => {
|
||||
this.query = this.lq.query(
|
||||
core.class.Status,
|
||||
{},
|
||||
(res) => {
|
||||
const first = this.docs === undefined
|
||||
|
||||
this.docs = res
|
||||
const newMap = new Map<string, Status[]>()
|
||||
for (const d of this.docs as Array<WithLookup<Status>>) {
|
||||
const n = d.name.toLowerCase().trim()
|
||||
newMap.set(n, [...(newMap.get(n) ?? []), d])
|
||||
}
|
||||
this.mgr = new StatusManager(res)
|
||||
this.docsByName = newMap
|
||||
statusStore.set(this.mgr)
|
||||
if (!first) {
|
||||
this.lqCallback()
|
||||
@ -83,9 +106,6 @@ export class StatusAggregationManager implements AggregationManager {
|
||||
resolve(this.mgr)
|
||||
},
|
||||
{
|
||||
lookup: {
|
||||
category: core.class.StatusCategory
|
||||
},
|
||||
sort: {
|
||||
rank: SortingOrder.Ascending
|
||||
}
|
||||
@ -98,6 +118,7 @@ export class StatusAggregationManager implements AggregationManager {
|
||||
|
||||
close (): void {
|
||||
this.query?.()
|
||||
this.categoryQuery?.()
|
||||
}
|
||||
|
||||
async notifyTx (tx: Tx): Promise<void> {
|
||||
@ -110,15 +131,13 @@ export class StatusAggregationManager implements AggregationManager {
|
||||
|
||||
async categorize (target: Array<Ref<Doc>>, attr: AnyAttribute): Promise<Array<Ref<Doc>>> {
|
||||
const mgr = await this.getManager()
|
||||
const idMap = mgr.getIdMap()
|
||||
|
||||
for (const sid of [...target]) {
|
||||
const s = mgr.getIdMap().get(sid as Ref<Status>) as WithLookup<Status>
|
||||
const s = idMap.get(sid as Ref<Status>) as WithLookup<Status>
|
||||
if (s !== undefined) {
|
||||
let statuses = mgr.getDocs()
|
||||
statuses = statuses.filter(
|
||||
(it) =>
|
||||
it.ofAttribute === attr._id &&
|
||||
it.name.toLowerCase().trim() === s.name.toLowerCase().trim() &&
|
||||
it._id !== s._id
|
||||
const statuses = (this.docsByName.get(s.name.toLowerCase().trim()) ?? []).filter(
|
||||
(it) => it.ofAttribute === attr._id && it._id !== s._id
|
||||
)
|
||||
target.push(...statuses.map((it) => it._id))
|
||||
}
|
||||
@ -140,10 +159,11 @@ export class StatusAggregationManager implements AggregationManager {
|
||||
// Fill custom sorting.
|
||||
let statuses = (await this.getManager()).getDocs()
|
||||
statuses = statuses.filter((it) => it.ofAttribute === attr._id)
|
||||
await this.categoryPromise
|
||||
statuses.sort((a, b) => {
|
||||
let ret = 0
|
||||
if (a.category !== undefined && b.category !== undefined) {
|
||||
ret = (a.$lookup?.category?.order ?? 0) - (b.$lookup?.category?.order ?? 0)
|
||||
ret = (this.statusCategory.get(a.category)?.order ?? 0) - (this.statusCategory.get(b.category)?.order ?? 0)
|
||||
}
|
||||
if (ret === 0) {
|
||||
if (a.name.toLowerCase().trim() === b.name.toLowerCase().trim()) {
|
||||
|
Loading…
Reference in New Issue
Block a user