重新处理了查询中total和randomRange的处理
This commit is contained in:
parent
f641a86710
commit
2683447e13
|
|
@ -20,6 +20,7 @@ export declare abstract class CascadeStore<ED extends EntityDict & BaseEntityDic
|
|||
protected abstract selectAbjointRow<T extends keyof ED, OP extends SelectOption, Cxt extends SyncContext<ED>>(entity: T, selection: ED[T]['Selection'], context: Cxt, option: OP): Partial<ED[T]['Schema']>[];
|
||||
protected abstract updateAbjointRow<T extends keyof ED, OP extends OperateOption, Cxt extends SyncContext<ED>>(entity: T, operation: ED[T]['Operation'], context: Cxt, option: OP): number;
|
||||
protected abstract selectAbjointRowAsync<T extends keyof ED, OP extends SelectOption, Cxt extends AsyncContext<ED>>(entity: T, selection: ED[T]['Selection'], context: Cxt, option: OP): Promise<Partial<ED[T]['Schema']>[]>;
|
||||
protected abstract countAsync<T extends keyof ED, OP extends SelectOption, Cxt extends AsyncContext<ED>>(entity: T, selection: Pick<ED[T]['Selection'], 'filter' | 'count'>, context: Cxt, option: OP): Promise<number>;
|
||||
protected abstract updateAbjointRowAsync<T extends keyof ED, OP extends OperateOption, Cxt extends AsyncContext<ED>>(entity: T, operation: ED[T]['Create'] | ED[T]['Update'] | ED[T]['Remove'], context: Cxt, option: OP): Promise<number>;
|
||||
protected abstract aggregateSync<T extends keyof ED, OP extends SelectOption, Cxt extends SyncContext<ED>>(entity: T, aggregation: ED[T]['Aggregation'], context: Cxt, option: OP): AggregationResult<ED[T]['Schema']>;
|
||||
protected abstract aggregateAsync<T extends keyof ED, OP extends SelectOption, Cxt extends AsyncContext<ED>>(entity: T, aggregation: ED[T]['Aggregation'], context: Cxt, option: OP): Promise<AggregationResult<ED[T]['Schema']>>;
|
||||
|
|
|
|||
|
|
@ -506,7 +506,7 @@ class CascadeStore extends RowStore_1.RowStore {
|
|||
}
|
||||
else {
|
||||
(0, assert_1.default)(relation instanceof Array);
|
||||
const { data: subProjection, filter: subFilter, indexFrom, count, sorter: subSorter } = projection2[attr];
|
||||
const { data: subProjection, filter: subFilter, indexFrom, count, sorter: subSorter, total, randomRange } = projection2[attr];
|
||||
const [entity2, foreignKey] = relation;
|
||||
const isAggr = attr.endsWith('$$aggr');
|
||||
const otmAggrFn = (result) => {
|
||||
|
|
@ -576,6 +576,7 @@ class CascadeStore extends RowStore_1.RowStore {
|
|||
data: subProjection,
|
||||
filter: filter2,
|
||||
sorter: subSorter,
|
||||
total,
|
||||
}, context, option);
|
||||
if (subRows instanceof Promise) {
|
||||
return subRows.then((subRowss) => dealWithSubRows(subRowss));
|
||||
|
|
@ -603,7 +604,9 @@ class CascadeStore extends RowStore_1.RowStore {
|
|||
filter: filter2,
|
||||
sorter: subSorter,
|
||||
indexFrom,
|
||||
count
|
||||
count,
|
||||
total,
|
||||
randomRange,
|
||||
}, context, option);
|
||||
if (subRows instanceof Promise) {
|
||||
return subRows.then((subRowss) => dealWithSubRows2(row, subRowss));
|
||||
|
|
@ -1608,15 +1611,29 @@ class CascadeStore extends RowStore_1.RowStore {
|
|||
});
|
||||
}
|
||||
async cascadeSelectAsync(entity, selection, context, option) {
|
||||
const { data, filter, indexFrom, count, sorter } = selection;
|
||||
const { data, filter, indexFrom, count, sorter, total, randomRange } = selection;
|
||||
const { projection, cascadeSelectionFns } = this.destructCascadeSelect(entity, data, context, this.cascadeSelectAsync, this.aggregateAsync, option);
|
||||
const rows = await this.selectAbjointRowAsync(entity, {
|
||||
const rows2 = await this.selectAbjointRowAsync(entity, {
|
||||
data: projection,
|
||||
filter,
|
||||
indexFrom,
|
||||
count,
|
||||
count: randomRange || count,
|
||||
sorter
|
||||
}, context, option);
|
||||
// 处理随机取值
|
||||
let rows = !randomRange ? rows2 : [];
|
||||
if (randomRange) {
|
||||
const possibility = count / rows2.length;
|
||||
let reduced = rows2.length - count;
|
||||
rows = rows2.filter(() => {
|
||||
const rand = Math.random();
|
||||
if (rand > possibility && reduced) {
|
||||
reduced--;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
if (!option.dontCollect) {
|
||||
this.addToResultSelections(entity, rows, context);
|
||||
}
|
||||
|
|
@ -1640,6 +1657,12 @@ class CascadeStore extends RowStore_1.RowStore {
|
|||
throw new types_1.OakRowUnexistedException(ruException);
|
||||
}
|
||||
}
|
||||
if (total) {
|
||||
const total2 = await this.countAsync(entity, selection, context, option);
|
||||
Object.assign(rows, {
|
||||
'#total': total2,
|
||||
});
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
async selectAsync(entity, selection, context, option) {
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ export type Selection<A extends ReadOnlyAction, D extends Projection, F extends
|
|||
sorter?: S;
|
||||
} & FilterPart<A, F> & {
|
||||
randomRange?: number;
|
||||
total?: number;
|
||||
};
|
||||
export interface EntityShape {
|
||||
id: PrimaryKey;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import assert from "assert";
|
||||
import {
|
||||
EntityDict, OperateOption, SelectOption, OperationResult, CreateAtAttribute,
|
||||
EntityDict, OperateOption, SelectOption, OperationResult, CreateAtAttribute,
|
||||
UpdateAtAttribute, AggregationResult, DeleteAtAttribute
|
||||
} from "../types/Entity";
|
||||
import { EntityDict as BaseEntityDict } from '../base-app-domain';
|
||||
|
|
@ -171,7 +171,7 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
|
|||
|
||||
const checkSorterNode = (
|
||||
entity2: keyof ED,
|
||||
sorterNode: NonNullable<ED[keyof ED]['Selection']['sorter']>,
|
||||
sorterNode: ED[keyof ED]['Selection']['sorter'],
|
||||
projectionNode: ED[keyof ED]['Selection']['data']) => {
|
||||
|
||||
const checkSortAttr = (e2: keyof ED, sortAttr: Record<string, any>, projNode: ED[keyof ED]['Selection']['data']) => {
|
||||
|
|
@ -202,7 +202,7 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
|
|||
}
|
||||
}
|
||||
}
|
||||
sorterNode.forEach(
|
||||
sorterNode!.forEach(
|
||||
(node) => {
|
||||
const { $attr } = node;
|
||||
checkSortAttr(entity2, $attr, projectionNode);
|
||||
|
|
@ -398,6 +398,13 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
|
|||
context: Cxt,
|
||||
option: OP): Promise<Partial<ED[T]['Schema']>[]>;
|
||||
|
||||
protected abstract countAsync<T extends keyof ED, OP extends SelectOption, Cxt extends AsyncContext<ED>>(
|
||||
entity: T,
|
||||
selection: Pick<ED[T]['Selection'], 'filter' | 'count'>,
|
||||
context: Cxt,
|
||||
option: OP
|
||||
): Promise<number>;
|
||||
|
||||
protected abstract updateAbjointRowAsync<T extends keyof ED, OP extends OperateOption, Cxt extends AsyncContext<ED>>(
|
||||
entity: T,
|
||||
operation: ED[T]['Create'] | ED[T]['Update'] | ED[T]['Remove'],
|
||||
|
|
@ -661,7 +668,7 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
|
|||
}
|
||||
else {
|
||||
assert(relation instanceof Array);
|
||||
const { data: subProjection, filter: subFilter, indexFrom, count, sorter: subSorter } = projection2[attr];
|
||||
const { data: subProjection, filter: subFilter, indexFrom, count, sorter: subSorter, total, randomRange } = projection2[attr];
|
||||
const [entity2, foreignKey] = relation;
|
||||
const isAggr = attr.endsWith('$$aggr');
|
||||
|
||||
|
|
@ -745,6 +752,7 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
|
|||
data: subProjection,
|
||||
filter: filter2,
|
||||
sorter: subSorter,
|
||||
total,
|
||||
}, context, option);
|
||||
if (subRows instanceof Promise) {
|
||||
return subRows.then(
|
||||
|
|
@ -777,7 +785,9 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
|
|||
filter: filter2,
|
||||
sorter: subSorter,
|
||||
indexFrom,
|
||||
count
|
||||
count,
|
||||
total,
|
||||
randomRange,
|
||||
}, context, option);
|
||||
if (subRows instanceof Promise) {
|
||||
return subRows.then(
|
||||
|
|
@ -1966,7 +1976,7 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
|
|||
selection: ED[T]['Selection'],
|
||||
context: Cxt,
|
||||
option: OP): Promise<Partial<ED[T]['Schema']>[]> {
|
||||
const { data, filter, indexFrom, count, sorter } = selection;
|
||||
const { data, filter, indexFrom, count, sorter, total, randomRange } = selection;
|
||||
const { projection, cascadeSelectionFns } = this.destructCascadeSelect(
|
||||
entity,
|
||||
data,
|
||||
|
|
@ -1975,14 +1985,30 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
|
|||
this.aggregateAsync,
|
||||
option);
|
||||
|
||||
const rows = await this.selectAbjointRowAsync(entity, {
|
||||
const rows2 = await this.selectAbjointRowAsync(entity, {
|
||||
data: projection,
|
||||
filter,
|
||||
indexFrom,
|
||||
count,
|
||||
count: randomRange || count,
|
||||
sorter
|
||||
}, context, option);
|
||||
|
||||
// 处理随机取值
|
||||
let rows = !randomRange ? rows2 : [];
|
||||
if (randomRange) {
|
||||
const possibility = count! / rows2.length;
|
||||
let reduced = rows2.length - count!;
|
||||
rows = rows2.filter(
|
||||
() => {
|
||||
const rand = Math.random();
|
||||
if (rand > possibility && reduced) {
|
||||
reduced--;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if (!option.dontCollect) {
|
||||
this.addToResultSelections(entity, rows, context);
|
||||
|
|
@ -2017,6 +2043,12 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
|
|||
}
|
||||
}
|
||||
|
||||
if (total) {
|
||||
const total2 = await this.countAsync(entity, selection, context, option);
|
||||
Object.assign(rows, {
|
||||
'#total': total2,
|
||||
});
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ export type Selection<A extends ReadOnlyAction,
|
|||
sorter?: S;
|
||||
} & FilterPart<A, F> & {
|
||||
randomRange?: number;
|
||||
total?: number;
|
||||
};
|
||||
|
||||
export interface EntityShape {
|
||||
|
|
|
|||
Loading…
Reference in New Issue