@uwdata/mosaic-core 0.8.0 → 0.10.0
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/dist/mosaic-core.js +1948 -664
- package/dist/mosaic-core.min.js +8 -8
- package/package.json +7 -7
- package/src/Coordinator.js +194 -49
- package/src/DataCubeIndexer.js +257 -198
- package/src/MosaicClient.js +3 -3
- package/src/QueryConsolidator.js +2 -2
- package/src/QueryManager.js +104 -94
- package/src/Selection.js +57 -21
- package/src/SelectionClause.js +161 -0
- package/src/connectors/rest.js +7 -0
- package/src/connectors/socket.js +7 -0
- package/src/connectors/wasm.js +2 -2
- package/src/index.js +10 -0
- package/src/util/AsyncDispatch.js +15 -5
- package/src/util/convert-arrow.js +14 -5
- package/src/util/index-columns.js +540 -0
- package/src/util/query-result.js +41 -8
- package/src/util/selection-types.ts +137 -0
- package/src/util/to-data-columns.js +71 -0
- package/src/FilterGroup.js +0 -70
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { SQLExpression } from '@uwdata/mosaic-sql';
|
|
2
|
+
import { MosaicClient } from '../MosaicClient.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Selection clause metadata to guide possible query optimizations.
|
|
6
|
+
* Sub-interfaces provide more information about the specifics of a
|
|
7
|
+
* given selection based on the selection type.
|
|
8
|
+
*/
|
|
9
|
+
export interface ClauseMetadata {
|
|
10
|
+
/**
|
|
11
|
+
* The selection type, such as `'point'`, `'interval'`, or `'match'`.
|
|
12
|
+
*/
|
|
13
|
+
type: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Selection clause metadata indicating selection of one or more discrete
|
|
18
|
+
* point values, typically based on equality or is distinctiveness checks.
|
|
19
|
+
*/
|
|
20
|
+
export interface PointMetadata extends ClauseMetadata {
|
|
21
|
+
type: 'point';
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** Text search matching methods. */
|
|
25
|
+
export type MatchMethod =
|
|
26
|
+
| 'contains'
|
|
27
|
+
| 'prefix'
|
|
28
|
+
| 'suffix'
|
|
29
|
+
| 'regexp'
|
|
30
|
+
| (string & {});
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Selection clause metadata indicating text search matching.
|
|
34
|
+
*/
|
|
35
|
+
export interface MatchMetadata extends ClauseMetadata {
|
|
36
|
+
type: MatchMethod;
|
|
37
|
+
/** The text search matching method used. */
|
|
38
|
+
method?: 'contains' | 'prefix' | 'suffix' | 'regexp' | (string & {});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Quantitative scale types. */
|
|
42
|
+
export type ScaleType =
|
|
43
|
+
| 'identity'
|
|
44
|
+
| 'linear'
|
|
45
|
+
| 'log'
|
|
46
|
+
| 'sqrt'
|
|
47
|
+
| 'pow'
|
|
48
|
+
| 'symlog'
|
|
49
|
+
| 'time'
|
|
50
|
+
| 'utc';
|
|
51
|
+
|
|
52
|
+
/** A data value interval extent. */
|
|
53
|
+
export type Extent = [number, number] | [Date, Date];
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Descriptor for a scale that maps a data domain to screen pixels.
|
|
57
|
+
*/
|
|
58
|
+
export interface Scale {
|
|
59
|
+
/** The scale type, such as `'linear'`, `'log'`, etc. */
|
|
60
|
+
type: ScaleType;
|
|
61
|
+
/** The scale domain, as an array of start and end data values. */
|
|
62
|
+
domain: Extent;
|
|
63
|
+
/**
|
|
64
|
+
* The scale range, as an array of start and end screen pixels.
|
|
65
|
+
* The range may be omitted for *identity* scales.
|
|
66
|
+
*/
|
|
67
|
+
range?: [number, number];
|
|
68
|
+
/** The base of the logarithm. For `'log'` scales only. */
|
|
69
|
+
base?: number;
|
|
70
|
+
/** The constant parameter. For `'symlog'` scales only. */
|
|
71
|
+
constant?: number;
|
|
72
|
+
/** The exponent parameter. For `'pow'` scales only. */
|
|
73
|
+
exponent?: number;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** A binning method name. */
|
|
77
|
+
export type BinMethod = 'floor' | 'ceil' | 'round';
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Selection clause metadata for one or more selected intervals. This
|
|
81
|
+
* metadata can be used to determine appropriate data-space binning
|
|
82
|
+
* schemes that correspond to pixel-level bins in screen space.
|
|
83
|
+
*/
|
|
84
|
+
export interface IntervalMetadata extends ClauseMetadata {
|
|
85
|
+
type: 'interval';
|
|
86
|
+
/**
|
|
87
|
+
* The interactive pixel size used by the generating component.
|
|
88
|
+
* Values larger than one indicate intervals that "snap-to" values
|
|
89
|
+
* greater than a single pixel. If unspecified, assumed to be `1`.
|
|
90
|
+
*/
|
|
91
|
+
pixelSize?: number;
|
|
92
|
+
/**
|
|
93
|
+
* An array of one or more scale descriptors that describe the
|
|
94
|
+
* mapping from data values to screen pixels.
|
|
95
|
+
*/
|
|
96
|
+
scales?: Scale[];
|
|
97
|
+
/**
|
|
98
|
+
* A hint for the binning method to use when discretizing the
|
|
99
|
+
* interval domain. If unspecified, the default is `'floor'`.
|
|
100
|
+
*/
|
|
101
|
+
bin?: BinMethod
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* A selection clause representing filtering criteria
|
|
106
|
+
* to apply within a Mosiac Selection.
|
|
107
|
+
*/
|
|
108
|
+
export interface SelectionClause {
|
|
109
|
+
/**
|
|
110
|
+
* A unique identifier (according to object equality) for the source
|
|
111
|
+
* component that generated this clause. In many cases, this is a
|
|
112
|
+
* reference to the originating component itself.
|
|
113
|
+
*/
|
|
114
|
+
source: any;
|
|
115
|
+
/**
|
|
116
|
+
* A set of Mosaic clients associated with this clause that should not
|
|
117
|
+
* be updated when this clause is applied in a cross-filtering context.
|
|
118
|
+
*/
|
|
119
|
+
clients?: Set<MosaicClient>;
|
|
120
|
+
/**
|
|
121
|
+
* A selected value associated with this clause. For example, for a 1D
|
|
122
|
+
* interval selection clause the value may be a [lo, hi] array.
|
|
123
|
+
*/
|
|
124
|
+
value: any;
|
|
125
|
+
/**
|
|
126
|
+
* A predicate SQL expression suitable for use in a query WHERE clause.
|
|
127
|
+
* The predicate should apply filtering criteria consistent with this
|
|
128
|
+
* clause's *value* property.
|
|
129
|
+
*/
|
|
130
|
+
predicate: SQLExpression | null;
|
|
131
|
+
/**
|
|
132
|
+
* Optional clause metadata that varies based on the selection type.
|
|
133
|
+
* The metadata can be used to optimize selection queries, for example
|
|
134
|
+
* by creating pre-aggregated data cubes when applicable.
|
|
135
|
+
*/
|
|
136
|
+
meta?: ClauseMetadata;
|
|
137
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { convertArrowColumn, isArrowTable } from './convert-arrow.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @typedef {Array | Int8Array | Uint8Array | Uint8ClampedArray
|
|
5
|
+
* | Int16Array | Uint16Array | Int32Array | Uint32Array
|
|
6
|
+
* | Float32Array | Float64Array
|
|
7
|
+
* } Arrayish - an Array or TypedArray
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @typedef {
|
|
12
|
+
* | { numRows: number, columns: Record<string,Arrayish> }
|
|
13
|
+
* | { numRows: number, values: Arrayish; }
|
|
14
|
+
* } DataColumns
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Convert input data to a set of column arrays.
|
|
19
|
+
* @param {any} data The input data.
|
|
20
|
+
* @returns {DataColumns} An object with named column arrays.
|
|
21
|
+
*/
|
|
22
|
+
export function toDataColumns(data) {
|
|
23
|
+
return isArrowTable(data)
|
|
24
|
+
? arrowToColumns(data)
|
|
25
|
+
: arrayToColumns(data);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Convert an Arrow table to a set of column arrays.
|
|
30
|
+
* @param {import('apache-arrow').Table} data An Apache Arrow Table.
|
|
31
|
+
* @returns {DataColumns} An object with named column arrays.
|
|
32
|
+
*/
|
|
33
|
+
function arrowToColumns(data) {
|
|
34
|
+
const { numRows, numCols, schema: { fields } } = data;
|
|
35
|
+
const columns = {};
|
|
36
|
+
|
|
37
|
+
for (let col = 0; col < numCols; ++col) {
|
|
38
|
+
const name = fields[col].name;
|
|
39
|
+
if (columns[name]) {
|
|
40
|
+
console.warn(`Redundant column name "${name}". Skipping...`);
|
|
41
|
+
} else {
|
|
42
|
+
columns[name] = convertArrowColumn(data.getChildAt(col));
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return { numRows, columns };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Convert an array of values to a set of column arrays.
|
|
51
|
+
* If the array values are objects, build out named columns.
|
|
52
|
+
* We use the keys of the first object as the column names.
|
|
53
|
+
* Otherwise, use a special "values" array.
|
|
54
|
+
* @param {object[]} data An array of data objects.
|
|
55
|
+
* @returns {DataColumns} An object with named column arrays.
|
|
56
|
+
*/
|
|
57
|
+
function arrayToColumns(data) {
|
|
58
|
+
const numRows = data.length;
|
|
59
|
+
if (typeof data[0] === 'object') {
|
|
60
|
+
const names = numRows ? Object.keys(data[0]) : [];
|
|
61
|
+
const columns = {};
|
|
62
|
+
if (names.length > 0) {
|
|
63
|
+
names.forEach(name => {
|
|
64
|
+
columns[name] = data.map(d => d[name]);
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
return { numRows, columns };
|
|
68
|
+
} else {
|
|
69
|
+
return { numRows, values: data };
|
|
70
|
+
}
|
|
71
|
+
}
|
package/src/FilterGroup.js
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import { DataCubeIndexer } from './DataCubeIndexer.js';
|
|
2
|
-
|
|
3
|
-
export class FilterGroup {
|
|
4
|
-
/**
|
|
5
|
-
* @param {import('./Coordinator.js').Coordinator} coordinator The Mosaic coordinator.
|
|
6
|
-
* @param {*} selection The shared filter selection.
|
|
7
|
-
* @param {*} index Boolean flag or options hash for data cube indexer.
|
|
8
|
-
* Falsy values disable indexing.
|
|
9
|
-
*/
|
|
10
|
-
constructor(coordinator, selection, index = true) {
|
|
11
|
-
/** @type import('./Coordinator.js').Coordinator */
|
|
12
|
-
this.mc = coordinator;
|
|
13
|
-
this.selection = selection;
|
|
14
|
-
this.clients = new Set();
|
|
15
|
-
this.indexer = index
|
|
16
|
-
? new DataCubeIndexer(this.mc, { ...index, selection })
|
|
17
|
-
: null;
|
|
18
|
-
|
|
19
|
-
const { value, activate } = this.handlers = {
|
|
20
|
-
value: () => this.update(),
|
|
21
|
-
activate: clause => this.indexer?.index(this.clients, clause)
|
|
22
|
-
};
|
|
23
|
-
selection.addEventListener('value', value);
|
|
24
|
-
selection.addEventListener('activate', activate);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
finalize() {
|
|
28
|
-
const { value, activate } = this.handlers;
|
|
29
|
-
this.selection.removeEventListener('value', value);
|
|
30
|
-
this.selection.removeEventListener('activate', activate);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
reset() {
|
|
34
|
-
this.indexer?.reset();
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
add(client) {
|
|
38
|
-
(this.clients = new Set(this.clients)).add(client);
|
|
39
|
-
return this;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
remove(client) {
|
|
43
|
-
if (this.clients.has(client)) {
|
|
44
|
-
(this.clients = new Set(this.clients)).delete(client);
|
|
45
|
-
}
|
|
46
|
-
return this;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Internal method to process a selection update.
|
|
51
|
-
* The return value is passed as a selection callback value.
|
|
52
|
-
* @returns {Promise} A Promise that resolves when the update completes.
|
|
53
|
-
*/
|
|
54
|
-
update() {
|
|
55
|
-
const { mc, indexer, clients, selection } = this;
|
|
56
|
-
const hasIndex = indexer?.index(clients);
|
|
57
|
-
return hasIndex
|
|
58
|
-
? indexer.update()
|
|
59
|
-
: defaultUpdate(mc, clients, selection);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function defaultUpdate(mc, clients, selection) {
|
|
64
|
-
return Promise.all(Array.from(clients).map(client => {
|
|
65
|
-
const filter = selection.predicate(client);
|
|
66
|
-
if (filter != null) {
|
|
67
|
-
return mc.updateClient(client, client.query(filter));
|
|
68
|
-
}
|
|
69
|
-
}));
|
|
70
|
-
}
|