in uui-db/src/IxSet.ts [137:245]
public query(query: DbQuery<TEntity>) {
const filter: DataQueryFilter<TEntity> = query.filter || {};
const filterFields = Object.keys(filter) as (keyof TEntity)[];
const filterFieldTypes = {} as Record<keyof TEntity, FilterConditionType>;
filterFields.forEach((f) => {
const condition = filter[f] as DataQueryFilterCondition<any>;
if (condition != null && typeof condition === 'object') {
if (condition.in) {
filterFieldTypes[f] = FilterConditionType.Multi;
}
} else {
filterFieldTypes[f] = FilterConditionType.Single;
}
});
let plans = this.indexes
.map((index) => {
if (filterFieldTypes[index.fields[0]]) {
let matchCount = 0;
const from: IndexKey<TEntity> = { [ID]: -Infinity } as any;
const to: IndexKey<TEntity> = { [ID]: +Infinity } as any;
const lookupFields = {} as Record<keyof TEntity, boolean>;
let isRemainingUnused = false;
for (let i = 0; i < index.fields.length; i++) {
const field: keyof TEntity = index.fields[i];
if (!isRemainingUnused && filterFieldTypes[field] === FilterConditionType.Single) {
lookupFields[field] = true;
from[field] = filter[field] as any;
to[field] = filter[field] as any;
matchCount++;
} else {
isRemainingUnused = true;
from[field] = -Infinity as any;
to[field] = Infinity as any;
}
}
let remainingFilter: DataQueryFilter<TEntity> = null;
filterFields
.filter((f) => !lookupFields[f])
.forEach((f) => {
if (!remainingFilter) {
remainingFilter = {};
}
remainingFilter[f] = filter[f];
});
const score = matchCount;
if (matchCount > 0) {
return {
score, index, from, to, remainingFilter,
};
}
}
return null;
})
.filter((p) => p != null);
plans = orderBy(plans, (plan) => plan.score, 'desc');
const plan = plans[0];
// const indexEntities = plan.index.tree.entries();
let treeIterator: IterableIterator<TEntity>;
if (plan) {
const indexIterator = plan.index.tree.entries(plan.from);
treeIterator = iterator(() => {
const next = indexIterator.next() as any;
if (!next.value) {
return next;
}
next.value = next.value[0];
if (plan.index.compare(next.value, plan.to) > 0) {
next.done = true;
next.value = null;
return next;
}
next.value = this.pk.get(next.value[ID]);
return next;
});
} else {
treeIterator = this.pk.values();
}
const result: TEntity[] = [];
const filterPredicate = getFilterPredicate(plan ? plan.remainingFilter : filter);
let current;
let index = 0;
let count = 0;
const rangeFrom = (query.range && query.range.from) || 0;
const rangeCount = (query.range && query.range.count) || Number.MAX_SAFE_INTEGER;
while (!(current = treeIterator.next()).done && count < rangeCount) {
const entity: TEntity = current.value;
const passedFilter = !filterPredicate || filterPredicate(entity);
if (passedFilter && index >= rangeFrom) {
result.push(entity);
count++;
}
index++;
}
return result;
}