@electric-sql/d2ts
Version:
D2TS is a TypeScript implementation of Differential Dataflow.
77 lines • 3.69 kB
JavaScript
import { reduce } from './reduce.js';
import { MultiSet } from '../../multiset.js';
import { SQLiteContext } from '../context.js';
/**
* Limits the number of results based on a comparator, with optional offset.
* This works on a keyed stream, where the key is the first element of the tuple
* The ordering is withing a key group, i.e. elements are sorted within a key group
* and the limit + offset is applied to that sorted group.
* To order the entire stream, key by the same value for all elements such as null.
*
* @param comparator - A function that compares two elements
* @param db - Optional SQLite database (can be injected via context)
* @param options - An optional object containing limit and offset properties
* @returns A piped operator that limits the number of results
*/
export function topK(comparator, options) {
const limit = options?.limit ?? Infinity;
const offset = options?.offset ?? 0;
return (stream) => {
// Get database from context if not provided explicitly
const database = options?.db || SQLiteContext.getDb();
if (!database) {
throw new Error('SQLite database is required for topK operator. ' +
'Provide it as a parameter or use withSQLite() to inject it.');
}
const reduced = stream.pipe(reduce((values) => {
// `values` is a list of tuples, first element is the value, second is the multiplicity
const consolidated = new MultiSet(values).consolidate();
const sortedValues = consolidated
.getInner()
.sort((a, b) => comparator(a[0], b[0]));
return sortedValues.slice(offset, offset + limit);
}, database));
return reduced;
};
}
/**
* Limits the number of results based on a comparator, with optional offset.
* This works on a keyed stream, where the key is the first element of the tuple
* The ordering is withing a key group, i.e. elements are sorted within a key group
* and the limit + offset is applied to that sorted group.
* To order the entire stream, key by the same value for all elements such as null.
* Adds the index of the element to the result as [key, [value, index]]
*
* @param comparator - A function that compares two elements
* @param db - Optional SQLite database (can be injected via context)
* @param options - An optional object containing limit and offset properties
* @returns A piped operator that orders the elements and limits the number of results
*/
export function topKWithIndex(comparator, options) {
const limit = options?.limit ?? Infinity;
const offset = options?.offset ?? 0;
return (stream) => {
// Get database from context if not provided explicitly
const database = options?.db || SQLiteContext.getDb();
if (!database) {
throw new Error('SQLite database is required for topKWithIndex operator. ' +
'Provide it as a parameter or use withSQLite() to inject it.');
}
const reduced = stream.pipe(reduce((values) => {
// `values` is a list of tuples, first element is the value, second is the multiplicity
const consolidated = new MultiSet(values).consolidate();
let i = offset;
const sortedValues = consolidated
.getInner()
.sort((a, b) => comparator(a[0], b[0]))
.slice(offset, offset + limit)
.map(([value, multiplicity]) => [
[value, i++],
multiplicity,
]);
return sortedValues;
}, database));
return reduced;
};
}
//# sourceMappingURL=topK.js.map