feat: sort & limit for jwt query

This commit is contained in:
DarkSky
2022-08-04 15:13:10 +08:00
parent 62cd0b4424
commit 78b24891d5
3 changed files with 60 additions and 47 deletions

View File

@@ -1,3 +1,5 @@
/* eslint-disable max-lines */
import { createNewSortInstance } from 'fast-sort';
import { deflateSync, inflateSync, strToU8, strFromU8 } from 'fflate';
import { Document as DocumentIndexer, DocumentSearchOptions } from 'flexsearch';
import { get, set, keys, del, createStore } from 'idb-keyval';
@@ -21,6 +23,13 @@ declare const JWT_DEV: boolean;
const logger = getLogger('BlockDB:indexing');
const logger_debug = getLogger('debug:BlockDB:indexing');
const naturalSort = createNewSortInstance({
comparer: new Intl.Collator(undefined, {
numeric: true,
sensitivity: 'base',
}).compare,
});
type ChangedState = ChangedStates extends Map<unknown, infer R> ? R : never;
export type BlockMetadata = QueryMetadata & { readonly id: string };
@@ -87,7 +96,11 @@ type BlockIndexedContent = {
query: QueryMetadata;
};
export type QueryIndexMetadata = Query<QueryMetadata>;
export type QueryIndexMetadata = Query<QueryMetadata> & {
$sort?: string;
$desc?: boolean;
$limit?: number;
};
export class BlockIndexer<
A extends AsyncDatabaseAdapter<C>,
@@ -299,13 +312,44 @@ export class BlockIndexer<
return this._blockIndexer.search(part_of_title_or_content as string);
}
private _testMetaKey(key: string) {
try {
const metadata = this._blockMetadata.values().next().value;
if (!metadata || typeof metadata !== 'object') return false;
return !!(key in metadata);
} catch (e) {
return false;
}
}
private _getSortedMetadata(sort: string, desc?: boolean) {
const sorter = naturalSort(Array.from(this._blockMetadata.entries()));
if (desc) return sorter.desc(([, m]) => m[sort]);
else return sorter.asc(([, m]) => m[sort]);
}
public query(query: QueryIndexMetadata) {
const matches: string[] = [];
const filter = sift<QueryMetadata>(query);
this._blockMetadata.forEach((value, key) => {
if (filter(value)) matches.push(key);
});
return matches;
const { $sort, $desc, $limit, ...condition } = query;
const filter = sift<QueryMetadata>(condition);
const limit = $limit || this._blockMetadata.size;
if ($sort && this._testMetaKey($sort)) {
const metadata = this._getSortedMetadata($sort, $desc);
metadata.forEach(([key, value]) => {
if (matches.length > limit) return;
if (filter(value)) matches.push(key);
});
return matches;
} else {
this._blockMetadata.forEach((value, key) => {
if (matches.length > limit) return;
if (filter(value)) matches.push(key);
});
return matches;
}
}
public getMetadata(ids: string[]): Array<BlockMetadata> {