@tanstack/db-ivm 0.1.13 → 0.1.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/cjs/d2.cjs.map +1 -1
- package/dist/cjs/graph.cjs.map +1 -1
- package/dist/cjs/hashing/hash.cjs.map +1 -1
- package/dist/cjs/index.cjs +6 -3
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +1 -0
- package/dist/cjs/indexes.cjs +1 -1
- package/dist/cjs/indexes.cjs.map +1 -1
- package/dist/cjs/multiset.cjs.map +1 -1
- package/dist/cjs/operators/concat.cjs.map +1 -1
- package/dist/cjs/operators/consolidate.cjs.map +1 -1
- package/dist/cjs/operators/count.cjs.map +1 -1
- package/dist/cjs/operators/debug.cjs.map +1 -1
- package/dist/cjs/operators/distinct.cjs.map +1 -1
- package/dist/cjs/operators/filter.cjs.map +1 -1
- package/dist/cjs/operators/filterBy.cjs.map +1 -1
- package/dist/cjs/operators/groupBy.cjs +2 -1
- package/dist/cjs/operators/groupBy.cjs.map +1 -1
- package/dist/cjs/operators/groupedTopKWithFractionalIndex.cjs +116 -0
- package/dist/cjs/operators/groupedTopKWithFractionalIndex.cjs.map +1 -0
- package/dist/cjs/operators/groupedTopKWithFractionalIndex.d.cts +50 -0
- package/dist/cjs/operators/index.d.cts +1 -0
- package/dist/cjs/operators/join.cjs.map +1 -1
- package/dist/cjs/operators/keying.cjs.map +1 -1
- package/dist/cjs/operators/map.cjs.map +1 -1
- package/dist/cjs/operators/negate.cjs.map +1 -1
- package/dist/cjs/operators/orderBy.cjs.map +1 -1
- package/dist/cjs/operators/output.cjs.map +1 -1
- package/dist/cjs/operators/pipe.cjs.map +1 -1
- package/dist/cjs/operators/reduce.cjs.map +1 -1
- package/dist/cjs/operators/tap.cjs.map +1 -1
- package/dist/cjs/operators/topK.cjs.map +1 -1
- package/dist/cjs/operators/topKArray.cjs +137 -0
- package/dist/cjs/operators/topKArray.cjs.map +1 -0
- package/dist/cjs/operators/topKArray.d.cts +59 -0
- package/dist/cjs/operators/topKState.cjs +73 -0
- package/dist/cjs/operators/topKState.cjs.map +1 -0
- package/dist/cjs/operators/topKState.d.cts +35 -0
- package/dist/cjs/operators/topKWithFractionalIndex.cjs +17 -208
- package/dist/cjs/operators/topKWithFractionalIndex.cjs.map +1 -1
- package/dist/cjs/operators/topKWithFractionalIndex.d.cts +4 -43
- package/dist/cjs/operators/topKWithFractionalIndexBTree.d.cts +5 -4
- package/dist/cjs/utils.cjs +21 -0
- package/dist/cjs/utils.cjs.map +1 -1
- package/dist/cjs/utils.d.cts +11 -0
- package/dist/esm/d2.js.map +1 -1
- package/dist/esm/graph.js.map +1 -1
- package/dist/esm/hashing/hash.js.map +1 -1
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +7 -4
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/indexes.js +1 -1
- package/dist/esm/indexes.js.map +1 -1
- package/dist/esm/multiset.js.map +1 -1
- package/dist/esm/operators/concat.js.map +1 -1
- package/dist/esm/operators/consolidate.js.map +1 -1
- package/dist/esm/operators/count.js.map +1 -1
- package/dist/esm/operators/debug.js.map +1 -1
- package/dist/esm/operators/distinct.js.map +1 -1
- package/dist/esm/operators/filter.js.map +1 -1
- package/dist/esm/operators/filterBy.js.map +1 -1
- package/dist/esm/operators/groupBy.js +2 -1
- package/dist/esm/operators/groupBy.js.map +1 -1
- package/dist/esm/operators/groupedTopKWithFractionalIndex.d.ts +50 -0
- package/dist/esm/operators/groupedTopKWithFractionalIndex.js +116 -0
- package/dist/esm/operators/groupedTopKWithFractionalIndex.js.map +1 -0
- package/dist/esm/operators/index.d.ts +1 -0
- package/dist/esm/operators/join.js.map +1 -1
- package/dist/esm/operators/keying.js.map +1 -1
- package/dist/esm/operators/map.js.map +1 -1
- package/dist/esm/operators/negate.js.map +1 -1
- package/dist/esm/operators/orderBy.js.map +1 -1
- package/dist/esm/operators/output.js.map +1 -1
- package/dist/esm/operators/pipe.js.map +1 -1
- package/dist/esm/operators/reduce.js.map +1 -1
- package/dist/esm/operators/tap.js.map +1 -1
- package/dist/esm/operators/topK.js.map +1 -1
- package/dist/esm/operators/topKArray.d.ts +59 -0
- package/dist/esm/operators/topKArray.js +137 -0
- package/dist/esm/operators/topKArray.js.map +1 -0
- package/dist/esm/operators/topKState.d.ts +35 -0
- package/dist/esm/operators/topKState.js +73 -0
- package/dist/esm/operators/topKState.js.map +1 -0
- package/dist/esm/operators/topKWithFractionalIndex.d.ts +4 -43
- package/dist/esm/operators/topKWithFractionalIndex.js +16 -207
- package/dist/esm/operators/topKWithFractionalIndex.js.map +1 -1
- package/dist/esm/operators/topKWithFractionalIndexBTree.d.ts +5 -4
- package/dist/esm/utils.d.ts +11 -0
- package/dist/esm/utils.js +22 -1
- package/dist/esm/utils.js.map +1 -1
- package/package.json +29 -29
- package/src/d2.ts +4 -4
- package/src/graph.ts +6 -6
- package/src/hashing/hash.ts +3 -3
- package/src/hashing/index.ts +2 -2
- package/src/index.ts +5 -4
- package/src/indexes.ts +8 -8
- package/src/multiset.ts +5 -5
- package/src/operators/concat.ts +6 -6
- package/src/operators/consolidate.ts +6 -6
- package/src/operators/count.ts +9 -9
- package/src/operators/debug.ts +8 -8
- package/src/operators/distinct.ts +11 -11
- package/src/operators/filter.ts +8 -8
- package/src/operators/filterBy.ts +7 -7
- package/src/operators/groupBy.ts +24 -23
- package/src/operators/groupedTopKWithFractionalIndex.ts +192 -0
- package/src/operators/index.ts +20 -19
- package/src/operators/join.ts +23 -23
- package/src/operators/keying.ts +4 -4
- package/src/operators/map.ts +8 -8
- package/src/operators/negate.ts +6 -6
- package/src/operators/orderBy.ts +26 -26
- package/src/operators/orderByBTree.ts +7 -7
- package/src/operators/output.ts +9 -9
- package/src/operators/pipe.ts +1 -1
- package/src/operators/reduce.ts +9 -9
- package/src/operators/tap.ts +8 -8
- package/src/operators/topK.ts +8 -8
- package/src/operators/topKArray.ts +255 -0
- package/src/operators/topKState.ts +111 -0
- package/src/operators/topKWithFractionalIndex.ts +36 -381
- package/src/operators/topKWithFractionalIndexBTree.ts +21 -30
- package/src/types.ts +22 -22
- package/src/utils.ts +36 -4
package/src/indexes.ts
CHANGED
|
@@ -33,9 +33,9 @@
|
|
|
33
33
|
* Prefixes extracted from array values: `['prefix', 'suffix']` → prefix='prefix'
|
|
34
34
|
*/
|
|
35
35
|
|
|
36
|
-
import { MultiSet } from
|
|
37
|
-
import { hash } from
|
|
38
|
-
import type { Hash } from
|
|
36
|
+
import { MultiSet } from './multiset.js'
|
|
37
|
+
import { hash } from './hashing/index.js'
|
|
38
|
+
import type { Hash } from './hashing/index.js'
|
|
39
39
|
|
|
40
40
|
// We use a symbol to represent the absence of a prefix, unprefixed values a stored
|
|
41
41
|
// against this key.
|
|
@@ -183,7 +183,7 @@ export class Index<TKey, TValue, TPrefix = any> {
|
|
|
183
183
|
return `Index(${JSON.stringify(
|
|
184
184
|
[...this.entries()],
|
|
185
185
|
undefined,
|
|
186
|
-
indent ? 2 : undefined
|
|
186
|
+
indent ? 2 : undefined,
|
|
187
187
|
)})`
|
|
188
188
|
}
|
|
189
189
|
|
|
@@ -325,7 +325,7 @@ export class Index<TKey, TValue, TPrefix = any> {
|
|
|
325
325
|
key,
|
|
326
326
|
mapOrSingleValue,
|
|
327
327
|
value,
|
|
328
|
-
multiplicity
|
|
328
|
+
multiplicity,
|
|
329
329
|
)
|
|
330
330
|
return
|
|
331
331
|
}
|
|
@@ -362,7 +362,7 @@ export class Index<TKey, TValue, TPrefix = any> {
|
|
|
362
362
|
key: TKey,
|
|
363
363
|
currentSingleValue: SingleValue<TValue>,
|
|
364
364
|
newValue: TValue,
|
|
365
|
-
multiplicity: number
|
|
365
|
+
multiplicity: number,
|
|
366
366
|
) {
|
|
367
367
|
const [currentValue, currentMultiplicity] = currentSingleValue
|
|
368
368
|
|
|
@@ -438,7 +438,7 @@ export class Index<TKey, TValue, TPrefix = any> {
|
|
|
438
438
|
* @returns A multiset of the joined values.
|
|
439
439
|
*/
|
|
440
440
|
join<TValue2>(
|
|
441
|
-
other: Index<TKey, TValue2
|
|
441
|
+
other: Index<TKey, TValue2>,
|
|
442
442
|
): MultiSet<[TKey, [TValue, TValue2]]> {
|
|
443
443
|
const result: Array<[[TKey, [TValue, TValue2]], number]> = []
|
|
444
444
|
// We want to iterate over the smaller of the two indexes to reduce the
|
|
@@ -499,7 +499,7 @@ function getPrefix<TValue, TPrefix>(value: TValue): TPrefix | NO_PREFIX {
|
|
|
499
499
|
* @returns True if the value is a single value, false otherwise.
|
|
500
500
|
*/
|
|
501
501
|
function isSingleValue<TValue>(
|
|
502
|
-
value: SingleValue<TValue> | unknown
|
|
502
|
+
value: SingleValue<TValue> | unknown,
|
|
503
503
|
): value is SingleValue<TValue> {
|
|
504
504
|
return Array.isArray(value)
|
|
505
505
|
}
|
package/src/multiset.ts
CHANGED
|
@@ -2,8 +2,8 @@ import {
|
|
|
2
2
|
DefaultMap,
|
|
3
3
|
chunkedArrayPush,
|
|
4
4
|
globalObjectIdGenerator,
|
|
5
|
-
} from
|
|
6
|
-
import { hash } from
|
|
5
|
+
} from './utils.js'
|
|
6
|
+
import { hash } from './hashing/index.js'
|
|
7
7
|
|
|
8
8
|
export type MultiSetArray<T> = Array<[T, number]>
|
|
9
9
|
export type KeyedData<T> = [key: string, value: T]
|
|
@@ -35,7 +35,7 @@ export class MultiSet<T> {
|
|
|
35
35
|
*/
|
|
36
36
|
map<U>(f: (data: T) => U): MultiSet<U> {
|
|
37
37
|
return new MultiSet(
|
|
38
|
-
this.#inner.map(([data, multiplicity]) => [f(data), multiplicity])
|
|
38
|
+
this.#inner.map(([data, multiplicity]) => [f(data), multiplicity]),
|
|
39
39
|
)
|
|
40
40
|
}
|
|
41
41
|
|
|
@@ -51,7 +51,7 @@ export class MultiSet<T> {
|
|
|
51
51
|
*/
|
|
52
52
|
negate(): MultiSet<T> {
|
|
53
53
|
return new MultiSet(
|
|
54
|
-
this.#inner.map(([data, multiplicity]) => [data, -multiplicity])
|
|
54
|
+
this.#inner.map(([data, multiplicity]) => [data, -multiplicity]),
|
|
55
55
|
)
|
|
56
56
|
}
|
|
57
57
|
|
|
@@ -142,7 +142,7 @@ export class MultiSet<T> {
|
|
|
142
142
|
const compositeKey = key + `|` + valueId
|
|
143
143
|
consolidated.set(
|
|
144
144
|
compositeKey,
|
|
145
|
-
(consolidated.get(compositeKey) || 0) + multiplicity
|
|
145
|
+
(consolidated.get(compositeKey) || 0) + multiplicity,
|
|
146
146
|
)
|
|
147
147
|
|
|
148
148
|
// Store the original data for the first occurrence
|
package/src/operators/concat.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { BinaryOperator, DifferenceStreamWriter } from
|
|
2
|
-
import { StreamBuilder } from
|
|
3
|
-
import type { IStreamBuilder, PipedOperator } from
|
|
1
|
+
import { BinaryOperator, DifferenceStreamWriter } from '../graph.js'
|
|
2
|
+
import { StreamBuilder } from '../d2.js'
|
|
3
|
+
import type { IStreamBuilder, PipedOperator } from '../types.js'
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Operator that concatenates two input streams
|
|
@@ -22,7 +22,7 @@ export class ConcatOperator<T, T2> extends BinaryOperator<T | T2> {
|
|
|
22
22
|
* @param other - The other stream to concatenate
|
|
23
23
|
*/
|
|
24
24
|
export function concat<T, T2>(
|
|
25
|
-
other: IStreamBuilder<T2
|
|
25
|
+
other: IStreamBuilder<T2>,
|
|
26
26
|
): PipedOperator<T, T | T2> {
|
|
27
27
|
return (stream: IStreamBuilder<T | T2>): IStreamBuilder<T | T2> => {
|
|
28
28
|
if (stream.graph !== other.graph) {
|
|
@@ -30,13 +30,13 @@ export function concat<T, T2>(
|
|
|
30
30
|
}
|
|
31
31
|
const output = new StreamBuilder<T | T2>(
|
|
32
32
|
stream.graph,
|
|
33
|
-
new DifferenceStreamWriter<T | T2>()
|
|
33
|
+
new DifferenceStreamWriter<T | T2>(),
|
|
34
34
|
)
|
|
35
35
|
const operator = new ConcatOperator<T, T2>(
|
|
36
36
|
stream.graph.getNextOperatorId(),
|
|
37
37
|
stream.connectReader(),
|
|
38
38
|
other.connectReader(),
|
|
39
|
-
output.writer
|
|
39
|
+
output.writer,
|
|
40
40
|
)
|
|
41
41
|
stream.graph.addOperator(operator)
|
|
42
42
|
return output
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { DifferenceStreamWriter, UnaryOperator } from
|
|
2
|
-
import { StreamBuilder } from
|
|
3
|
-
import { MultiSet } from
|
|
4
|
-
import type { IStreamBuilder, PipedOperator } from
|
|
1
|
+
import { DifferenceStreamWriter, UnaryOperator } from '../graph.js'
|
|
2
|
+
import { StreamBuilder } from '../d2.js'
|
|
3
|
+
import { MultiSet } from '../multiset.js'
|
|
4
|
+
import type { IStreamBuilder, PipedOperator } from '../types.js'
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Operator that consolidates collections
|
|
@@ -36,12 +36,12 @@ export function consolidate<T>(): PipedOperator<T, T> {
|
|
|
36
36
|
return (stream: IStreamBuilder<T>): IStreamBuilder<T> => {
|
|
37
37
|
const output = new StreamBuilder<T>(
|
|
38
38
|
stream.graph,
|
|
39
|
-
new DifferenceStreamWriter<T>()
|
|
39
|
+
new DifferenceStreamWriter<T>(),
|
|
40
40
|
)
|
|
41
41
|
const operator = new ConsolidateOperator<T>(
|
|
42
42
|
stream.graph.getNextOperatorId(),
|
|
43
43
|
stream.connectReader(),
|
|
44
|
-
output.writer
|
|
44
|
+
output.writer,
|
|
45
45
|
)
|
|
46
46
|
stream.graph.addOperator(operator)
|
|
47
47
|
return output
|
package/src/operators/count.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { DifferenceStreamWriter } from
|
|
2
|
-
import { StreamBuilder } from
|
|
3
|
-
import { ReduceOperator } from
|
|
4
|
-
import type { DifferenceStreamReader } from
|
|
5
|
-
import type { IStreamBuilder, KeyValue } from
|
|
1
|
+
import { DifferenceStreamWriter } from '../graph.js'
|
|
2
|
+
import { StreamBuilder } from '../d2.js'
|
|
3
|
+
import { ReduceOperator } from './reduce.js'
|
|
4
|
+
import type { DifferenceStreamReader } from '../graph.js'
|
|
5
|
+
import type { IStreamBuilder, KeyValue } from '../types.js'
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Operator that counts elements by key (version-free)
|
|
@@ -11,7 +11,7 @@ export class CountOperator<K, V> extends ReduceOperator<K, V, number> {
|
|
|
11
11
|
constructor(
|
|
12
12
|
id: number,
|
|
13
13
|
inputA: DifferenceStreamReader<[K, V]>,
|
|
14
|
-
output: DifferenceStreamWriter<[K, number]
|
|
14
|
+
output: DifferenceStreamWriter<[K, number]>,
|
|
15
15
|
) {
|
|
16
16
|
const countInner = (vals: Array<[V, number]>): Array<[number, number]> => {
|
|
17
17
|
let totalCount = 0
|
|
@@ -34,16 +34,16 @@ export function count<
|
|
|
34
34
|
T,
|
|
35
35
|
>() {
|
|
36
36
|
return (
|
|
37
|
-
stream: IStreamBuilder<T
|
|
37
|
+
stream: IStreamBuilder<T>,
|
|
38
38
|
): IStreamBuilder<KeyValue<KType, number>> => {
|
|
39
39
|
const output = new StreamBuilder<KeyValue<KType, number>>(
|
|
40
40
|
stream.graph,
|
|
41
|
-
new DifferenceStreamWriter<KeyValue<KType, number>>()
|
|
41
|
+
new DifferenceStreamWriter<KeyValue<KType, number>>(),
|
|
42
42
|
)
|
|
43
43
|
const operator = new CountOperator<KType, VType>(
|
|
44
44
|
stream.graph.getNextOperatorId(),
|
|
45
45
|
stream.connectReader() as DifferenceStreamReader<KeyValue<KType, VType>>,
|
|
46
|
-
output.writer
|
|
46
|
+
output.writer,
|
|
47
47
|
)
|
|
48
48
|
stream.graph.addOperator(operator)
|
|
49
49
|
return output
|
package/src/operators/debug.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { DifferenceStreamWriter, UnaryOperator } from
|
|
2
|
-
import { StreamBuilder } from
|
|
3
|
-
import type { IStreamBuilder, PipedOperator } from
|
|
4
|
-
import type { DifferenceStreamReader } from
|
|
1
|
+
import { DifferenceStreamWriter, UnaryOperator } from '../graph.js'
|
|
2
|
+
import { StreamBuilder } from '../d2.js'
|
|
3
|
+
import type { IStreamBuilder, PipedOperator } from '../types.js'
|
|
4
|
+
import type { DifferenceStreamReader } from '../graph.js'
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Operator that logs debug information about the stream
|
|
@@ -15,7 +15,7 @@ export class DebugOperator<T> extends UnaryOperator<T> {
|
|
|
15
15
|
inputA: DifferenceStreamReader<T>,
|
|
16
16
|
output: DifferenceStreamWriter<T>,
|
|
17
17
|
name: string,
|
|
18
|
-
indent: boolean = false
|
|
18
|
+
indent: boolean = false,
|
|
19
19
|
) {
|
|
20
20
|
super(id, inputA, output)
|
|
21
21
|
this.#name = name
|
|
@@ -37,19 +37,19 @@ export class DebugOperator<T> extends UnaryOperator<T> {
|
|
|
37
37
|
*/
|
|
38
38
|
export function debug<T>(
|
|
39
39
|
name: string,
|
|
40
|
-
indent: boolean = false
|
|
40
|
+
indent: boolean = false,
|
|
41
41
|
): PipedOperator<T, T> {
|
|
42
42
|
return (stream: IStreamBuilder<T>): IStreamBuilder<T> => {
|
|
43
43
|
const output = new StreamBuilder<T>(
|
|
44
44
|
stream.graph,
|
|
45
|
-
new DifferenceStreamWriter<T>()
|
|
45
|
+
new DifferenceStreamWriter<T>(),
|
|
46
46
|
)
|
|
47
47
|
const operator = new DebugOperator<T>(
|
|
48
48
|
stream.graph.getNextOperatorId(),
|
|
49
49
|
stream.connectReader(),
|
|
50
50
|
output.writer,
|
|
51
51
|
name,
|
|
52
|
-
indent
|
|
52
|
+
indent,
|
|
53
53
|
)
|
|
54
54
|
stream.graph.addOperator(operator)
|
|
55
55
|
return output
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { DifferenceStreamWriter, UnaryOperator } from
|
|
2
|
-
import { StreamBuilder } from
|
|
3
|
-
import { hash } from
|
|
4
|
-
import { MultiSet } from
|
|
5
|
-
import type { Hash } from
|
|
6
|
-
import type { DifferenceStreamReader } from
|
|
7
|
-
import type { IStreamBuilder, KeyValue } from
|
|
1
|
+
import { DifferenceStreamWriter, UnaryOperator } from '../graph.js'
|
|
2
|
+
import { StreamBuilder } from '../d2.js'
|
|
3
|
+
import { hash } from '../hashing/index.js'
|
|
4
|
+
import { MultiSet } from '../multiset.js'
|
|
5
|
+
import type { Hash } from '../hashing/index.js'
|
|
6
|
+
import type { DifferenceStreamReader } from '../graph.js'
|
|
7
|
+
import type { IStreamBuilder, KeyValue } from '../types.js'
|
|
8
8
|
|
|
9
9
|
type Multiplicity = number
|
|
10
10
|
|
|
@@ -23,7 +23,7 @@ export class DistinctOperator<
|
|
|
23
23
|
id: number,
|
|
24
24
|
input: DifferenceStreamReader<T>,
|
|
25
25
|
output: DifferenceStreamWriter<KeyValue<number, GetValue<T>>>,
|
|
26
|
-
by: (value: T) => any = (value: T) => value
|
|
26
|
+
by: (value: T) => any = (value: T) => value,
|
|
27
27
|
) {
|
|
28
28
|
super(id, input, output)
|
|
29
29
|
this.#by = by
|
|
@@ -83,18 +83,18 @@ export class DistinctOperator<
|
|
|
83
83
|
* Removes duplicate values
|
|
84
84
|
*/
|
|
85
85
|
export function distinct<T extends KeyValue<any, any>>(
|
|
86
|
-
by: (value: T) => any = (value: T) => value
|
|
86
|
+
by: (value: T) => any = (value: T) => value,
|
|
87
87
|
) {
|
|
88
88
|
return (stream: IStreamBuilder<T>): IStreamBuilder<T> => {
|
|
89
89
|
const output = new StreamBuilder<T>(
|
|
90
90
|
stream.graph,
|
|
91
|
-
new DifferenceStreamWriter<T>()
|
|
91
|
+
new DifferenceStreamWriter<T>(),
|
|
92
92
|
)
|
|
93
93
|
const operator = new DistinctOperator<T>(
|
|
94
94
|
stream.graph.getNextOperatorId(),
|
|
95
95
|
stream.connectReader(),
|
|
96
96
|
output.writer,
|
|
97
|
-
by
|
|
97
|
+
by,
|
|
98
98
|
)
|
|
99
99
|
stream.graph.addOperator(operator)
|
|
100
100
|
return output
|
package/src/operators/filter.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { DifferenceStreamWriter, LinearUnaryOperator } from
|
|
2
|
-
import { StreamBuilder } from
|
|
3
|
-
import type { IStreamBuilder, PipedOperator } from
|
|
4
|
-
import type { DifferenceStreamReader } from
|
|
5
|
-
import type { MultiSet } from
|
|
1
|
+
import { DifferenceStreamWriter, LinearUnaryOperator } from '../graph.js'
|
|
2
|
+
import { StreamBuilder } from '../d2.js'
|
|
3
|
+
import type { IStreamBuilder, PipedOperator } from '../types.js'
|
|
4
|
+
import type { DifferenceStreamReader } from '../graph.js'
|
|
5
|
+
import type { MultiSet } from '../multiset.js'
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Operator that filters elements from the input stream
|
|
@@ -14,7 +14,7 @@ export class FilterOperator<T> extends LinearUnaryOperator<T, T> {
|
|
|
14
14
|
id: number,
|
|
15
15
|
inputA: DifferenceStreamReader<T>,
|
|
16
16
|
output: DifferenceStreamWriter<T>,
|
|
17
|
-
f: (data: T) => boolean
|
|
17
|
+
f: (data: T) => boolean,
|
|
18
18
|
) {
|
|
19
19
|
super(id, inputA, output)
|
|
20
20
|
this.#f = f
|
|
@@ -33,13 +33,13 @@ export function filter<T>(f: (data: T) => boolean): PipedOperator<T, T> {
|
|
|
33
33
|
return (stream: IStreamBuilder<T>): IStreamBuilder<T> => {
|
|
34
34
|
const output = new StreamBuilder<T>(
|
|
35
35
|
stream.graph,
|
|
36
|
-
new DifferenceStreamWriter<T>()
|
|
36
|
+
new DifferenceStreamWriter<T>(),
|
|
37
37
|
)
|
|
38
38
|
const operator = new FilterOperator<T>(
|
|
39
39
|
stream.graph.getNextOperatorId(),
|
|
40
40
|
stream.connectReader(),
|
|
41
41
|
output.writer,
|
|
42
|
-
f
|
|
42
|
+
f,
|
|
43
43
|
)
|
|
44
44
|
stream.graph.addOperator(operator)
|
|
45
45
|
return output
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { map } from
|
|
2
|
-
import { innerJoin } from
|
|
3
|
-
import { consolidate } from
|
|
4
|
-
import type { IStreamBuilder, KeyValue, PipedOperator } from
|
|
1
|
+
import { map } from './map.js'
|
|
2
|
+
import { innerJoin } from './join.js'
|
|
3
|
+
import { consolidate } from './consolidate.js'
|
|
4
|
+
import type { IStreamBuilder, KeyValue, PipedOperator } from '../types.js'
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Filters the elements of a keyed stream, by keys of another stream.
|
|
@@ -15,16 +15,16 @@ export function filterBy<
|
|
|
15
15
|
V1 extends T extends KeyValue<infer _KT, infer VT> ? VT : never,
|
|
16
16
|
T,
|
|
17
17
|
>(
|
|
18
|
-
other: IStreamBuilder<KeyValue<K, unknown
|
|
18
|
+
other: IStreamBuilder<KeyValue<K, unknown>>,
|
|
19
19
|
): PipedOperator<T, KeyValue<K, V1>> {
|
|
20
20
|
return (stream: IStreamBuilder<T>): IStreamBuilder<KeyValue<K, V1>> => {
|
|
21
21
|
const otherKeys = other.pipe(
|
|
22
|
-
map(([key, _]) => [key, null] as KeyValue<K, null>)
|
|
22
|
+
map(([key, _]) => [key, null] as KeyValue<K, null>),
|
|
23
23
|
)
|
|
24
24
|
return stream.pipe(
|
|
25
25
|
innerJoin(otherKeys),
|
|
26
26
|
map(([key, [value, _]]) => [key, value] as KeyValue<K, V1>),
|
|
27
|
-
consolidate()
|
|
27
|
+
consolidate(),
|
|
28
28
|
)
|
|
29
29
|
}
|
|
30
30
|
}
|
package/src/operators/groupBy.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
1
|
+
import { serializeValue } from '../utils.js'
|
|
2
|
+
import { map } from './map.js'
|
|
3
|
+
import { reduce } from './reduce.js'
|
|
4
|
+
import type { IStreamBuilder, KeyValue } from '../types.js'
|
|
4
5
|
|
|
5
6
|
type GroupKey = Record<string, unknown>
|
|
6
7
|
|
|
@@ -26,7 +27,7 @@ type AggregatesReturnType<T, A> = {
|
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
function isPipedAggregateFunction<T, R>(
|
|
29
|
-
aggregate: AggregateFunction<T, R
|
|
30
|
+
aggregate: AggregateFunction<T, R>,
|
|
30
31
|
): aggregate is PipedAggregateFunction<T, R> {
|
|
31
32
|
return `pipe` in aggregate
|
|
32
33
|
}
|
|
@@ -45,20 +46,20 @@ export function groupBy<
|
|
|
45
46
|
|
|
46
47
|
const basicAggregates = Object.fromEntries(
|
|
47
48
|
Object.entries(aggregates).filter(
|
|
48
|
-
([_, aggregate]) => !isPipedAggregateFunction(aggregate)
|
|
49
|
-
)
|
|
49
|
+
([_, aggregate]) => !isPipedAggregateFunction(aggregate),
|
|
50
|
+
),
|
|
50
51
|
) as Record<string, BasicAggregateFunction<T, any, any>>
|
|
51
52
|
|
|
52
53
|
// @ts-expect-error - TODO: we don't use this yet, but we will
|
|
53
54
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
54
55
|
const pipedAggregates = Object.fromEntries(
|
|
55
56
|
Object.entries(aggregates).filter(([_, aggregate]) =>
|
|
56
|
-
isPipedAggregateFunction(aggregate)
|
|
57
|
-
)
|
|
57
|
+
isPipedAggregateFunction(aggregate),
|
|
58
|
+
),
|
|
58
59
|
) as Record<string, PipedAggregateFunction<T, any>>
|
|
59
60
|
|
|
60
61
|
return (
|
|
61
|
-
stream: IStreamBuilder<T
|
|
62
|
+
stream: IStreamBuilder<T>,
|
|
62
63
|
): IStreamBuilder<KeyValue<string, ResultType>> => {
|
|
63
64
|
// Special key to store the original key object
|
|
64
65
|
const KEY_SENTINEL = `__original_key__`
|
|
@@ -67,7 +68,7 @@ export function groupBy<
|
|
|
67
68
|
const withKeysAndValues = stream.pipe(
|
|
68
69
|
map((data) => {
|
|
69
70
|
const key = keyExtractor(data)
|
|
70
|
-
const keyString =
|
|
71
|
+
const keyString = serializeValue(key)
|
|
71
72
|
|
|
72
73
|
// Create values object with pre-aggregated values
|
|
73
74
|
const values: Record<string, unknown> = {}
|
|
@@ -81,7 +82,7 @@ export function groupBy<
|
|
|
81
82
|
}
|
|
82
83
|
|
|
83
84
|
return [keyString, values] as KeyValue<string, Record<string, unknown>>
|
|
84
|
-
})
|
|
85
|
+
}),
|
|
85
86
|
)
|
|
86
87
|
|
|
87
88
|
// Then reduce to compute aggregates
|
|
@@ -107,13 +108,13 @@ export function groupBy<
|
|
|
107
108
|
// Apply each aggregate function
|
|
108
109
|
for (const [name, aggregate] of Object.entries(basicAggregates)) {
|
|
109
110
|
const preValues = values.map(
|
|
110
|
-
([v, m]) => [v[name], m] as [any, number]
|
|
111
|
+
([v, m]) => [v[name], m] as [any, number],
|
|
111
112
|
)
|
|
112
113
|
result[name] = aggregate.reduce(preValues)
|
|
113
114
|
}
|
|
114
115
|
|
|
115
116
|
return [[result, 1]]
|
|
116
|
-
})
|
|
117
|
+
}),
|
|
117
118
|
)
|
|
118
119
|
|
|
119
120
|
// Finally map to extract the key and include all values
|
|
@@ -139,7 +140,7 @@ export function groupBy<
|
|
|
139
140
|
|
|
140
141
|
// Return with the string key instead of the object
|
|
141
142
|
return [keyString, result] as KeyValue<string, ResultType>
|
|
142
|
-
})
|
|
143
|
+
}),
|
|
143
144
|
)
|
|
144
145
|
}
|
|
145
146
|
}
|
|
@@ -148,7 +149,7 @@ export function groupBy<
|
|
|
148
149
|
* Creates a sum aggregate function
|
|
149
150
|
*/
|
|
150
151
|
export function sum<T>(
|
|
151
|
-
valueExtractor: (value: T) => number = (v) => v as unknown as number
|
|
152
|
+
valueExtractor: (value: T) => number = (v) => v as unknown as number,
|
|
152
153
|
): AggregateFunction<T, number, number> {
|
|
153
154
|
return {
|
|
154
155
|
preMap: (data: T) => valueExtractor(data),
|
|
@@ -166,7 +167,7 @@ export function sum<T>(
|
|
|
166
167
|
* Creates a count aggregate function
|
|
167
168
|
*/
|
|
168
169
|
export function count<T>(
|
|
169
|
-
valueExtractor: (value: T) => any = (v) => v
|
|
170
|
+
valueExtractor: (value: T) => any = (v) => v,
|
|
170
171
|
): AggregateFunction<T, number, number> {
|
|
171
172
|
return {
|
|
172
173
|
// Count only not-null values (the `== null` comparison gives true for both null and undefined)
|
|
@@ -185,7 +186,7 @@ export function count<T>(
|
|
|
185
186
|
* Creates an average aggregate function
|
|
186
187
|
*/
|
|
187
188
|
export function avg<T>(
|
|
188
|
-
valueExtractor: (value: T) => number = (v) => v as unknown as number
|
|
189
|
+
valueExtractor: (value: T) => number = (v) => v as unknown as number,
|
|
189
190
|
): AggregateFunction<T, number, { sum: number; count: number }> {
|
|
190
191
|
return {
|
|
191
192
|
preMap: (data: T) => ({
|
|
@@ -222,10 +223,10 @@ export function min<T extends CanMinMax>(): AggregateFunction<
|
|
|
222
223
|
T | undefined
|
|
223
224
|
>
|
|
224
225
|
export function min<T, V extends CanMinMax>(
|
|
225
|
-
valueExtractor: (value: T) => V
|
|
226
|
+
valueExtractor: (value: T) => V,
|
|
226
227
|
): AggregateFunction<T, V | undefined, V | undefined>
|
|
227
228
|
export function min<T, V extends CanMinMax>(
|
|
228
|
-
valueExtractor?: (value: T) => V
|
|
229
|
+
valueExtractor?: (value: T) => V,
|
|
229
230
|
): AggregateFunction<T, V | undefined, V | undefined> {
|
|
230
231
|
const extractor = valueExtractor ?? ((v: T) => v as unknown as V)
|
|
231
232
|
return {
|
|
@@ -252,10 +253,10 @@ export function max<T extends CanMinMax>(): AggregateFunction<
|
|
|
252
253
|
T | undefined
|
|
253
254
|
>
|
|
254
255
|
export function max<T, V extends CanMinMax>(
|
|
255
|
-
valueExtractor: (value: T) => V
|
|
256
|
+
valueExtractor: (value: T) => V,
|
|
256
257
|
): AggregateFunction<T, V | undefined, V | undefined>
|
|
257
258
|
export function max<T, V extends CanMinMax>(
|
|
258
|
-
valueExtractor?: (value: T) => V
|
|
259
|
+
valueExtractor?: (value: T) => V,
|
|
259
260
|
): AggregateFunction<T, V | undefined, V | undefined> {
|
|
260
261
|
const extractor = valueExtractor ?? ((v: T) => v as unknown as V)
|
|
261
262
|
return {
|
|
@@ -278,7 +279,7 @@ export function max<T, V extends CanMinMax>(
|
|
|
278
279
|
* @param valueExtractor Function to extract a numeric value from each data entry
|
|
279
280
|
*/
|
|
280
281
|
export function median<T>(
|
|
281
|
-
valueExtractor: (value: T) => number = (v) => v as unknown as number
|
|
282
|
+
valueExtractor: (value: T) => number = (v) => v as unknown as number,
|
|
282
283
|
): AggregateFunction<T, number, Array<number>> {
|
|
283
284
|
return {
|
|
284
285
|
preMap: (data: T) => [valueExtractor(data)],
|
|
@@ -326,7 +327,7 @@ export function median<T>(
|
|
|
326
327
|
* @param valueExtractor Function to extract a value from each data entry
|
|
327
328
|
*/
|
|
328
329
|
export function mode<T>(
|
|
329
|
-
valueExtractor: (value: T) => number = (v) => v as unknown as number
|
|
330
|
+
valueExtractor: (value: T) => number = (v) => v as unknown as number,
|
|
330
331
|
): AggregateFunction<T, number, Map<number, number>> {
|
|
331
332
|
return {
|
|
332
333
|
preMap: (data: T) => {
|