Skip to content

Commit

Permalink
feat: association in v2 engine (new algo)
Browse files Browse the repository at this point in the history
  • Loading branch information
ObservedObserver committed Sep 27, 2021
1 parent 5013547 commit 284413a
Show file tree
Hide file tree
Showing 11 changed files with 382 additions and 79 deletions.
2 changes: 1 addition & 1 deletion packages/connectors/app-config.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"port": 2333,
"clickhouse": {
"protocol": "http:",
"protocol": "http",
"host": "localhost",
"port": 8123
}
Expand Down
52 changes: 50 additions & 2 deletions packages/connectors/app/controllers/clickHouseProxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,15 @@ import { sendFailResponse, sendSuccessResponse } from "../utils";
interface CHProxyProps {
[key: string]: string
}
export async function CHSelectProxy (ctx: Context) {

async function CHQuery (sql: string): Promise<string> {
const config = useGlobalStore().getConfig();
const res = await axios(`${config.clickhouse.protocol}://${config.clickhouse.host}:${config.clickhouse.port}?query=${sql}`);
console.log('res data', res.data)
return res.data;
}

export async function CHGeneralProxy (ctx: Context) {
// const props = ctx.request.body as CHProxyProps;
// http://localhost:8123?query=SELECT * from datasets.suicideRate;
const config = useGlobalStore().getConfig();
Expand All @@ -19,4 +27,44 @@ export async function CHSelectProxy (ctx: Context) {
console.error(error);
sendFailResponse(ctx, error)
}
}
}

export async function CHDBListProxy (ctx: Context) {
try {
const rawData = await CHQuery('SHOW DATABASES;')
const list = rawData.split('\n').slice(1);
sendSuccessResponse(ctx, list)
} catch (error) {
console.error(error);
sendFailResponse(ctx, error);
}
}

export async function CHTableListProxy (ctx: Context) {
try {
const rawData = await CHQuery('SHOW TABLES FROM DATASETS;')
const list = rawData.split('\n');
sendSuccessResponse(ctx, list)
} catch (error) {
console.error(error);
sendFailResponse(ctx, error);
}
}

export async function CHTableDescProxy (ctx: Context) {
try {
const url = ctx.request.URL;
const tableName = url.searchParams.get('table');
const rawData = await CHQuery(`DESCRIBE TABLE ${tableName}`);
const list = rawData.split('\n');
sendSuccessResponse(ctx, list)
} catch (error) {
console.error(error);
sendFailResponse(ctx, error);
}
}

setTimeout(() => {
CHQuery('describe table datasets.suicideRate;').then(() => {}).catch(console.error);
CHQuery('show tables from datasets;').then(() => {}).catch(console.error);
}, 3000)
4 changes: 2 additions & 2 deletions packages/connectors/app/router.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import Router from '@koa/router';
// import { UserController } from './controllers/user';
import { CHSelectProxy } from './controllers/clickHouseProxy';
import { CHGeneralProxy } from './controllers/clickHouseProxy';
const router = new Router();

router.get('/api/clickhouse/select', CHSelectProxy);
router.get('/api/clickhouse/general', CHGeneralProxy);

// router.post('/api/login', UserController.login);
// router.post('/api/register', UserController.register);
Expand Down
67 changes: 67 additions & 0 deletions packages/frontend/src/pages/lts/association/assCharts.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import React from "react";
// import VisDescription from "../../../plugins/visSummary/description";
// import useDigDimension, { DigDimensionProps } from "./digDimension";
import BaseChart from "../../../visBuilder/vegaBase";
import { FieldSummary, Subspace } from "../../../service";
// import { IconButton, Stack } from "office-ui-fabric-react";
import { IInsightSpace, Specification } from "visual-insights";
import { PreferencePanelConfig } from "../../../components/preference";
import { IRow } from "../../../interfaces";

export interface IVizSpace extends IInsightSpace {
schema: Specification;
dataView: IRow[]
}

interface AssociationProps {
visualConfig: PreferencePanelConfig;
// subspaceList: Subspace[];
vizList: IVizSpace[];
fieldScores: FieldSummary[];
dataSource: IRow[];
onSelectView: (index: number) => void
}
const AssociationCharts: React.FC<AssociationProps> = props => {
const { vizList, onSelectView, visualConfig, fieldScores, dataSource } = props;
// const { dataSource, fieldScores } = digDimensionProps;
// const relatedCharts = useDigDimension(digDimensionProps);
const fieldFeatures = fieldScores.map(f => ({
name: f.fieldName,
type: f.type
}));
//className="ms-Grid"
return (
<div style={{ border: "solid 1px #bfbfbf", marginTop: '2em' }}>

<div style={{ display: 'flex', flexWrap: 'wrap', overflow: 'auto' }}>
{vizList.map((view, i) => {
return (
<div key={`associate-row-${i}`}
// className="ms-Grid-row"
dir="ltr"
style={{
// border: "solid 1px #bfbfbf",
margin: "1em",
padding: "1em"
}}
>
<BaseChart
fixedWidth={false}
aggregator={visualConfig.aggregator}
defaultAggregated={view.schema.geomType && view.schema.geomType.includes("point") ? false : true}
defaultStack={visualConfig.defaultStack}
dimensions={view.dimensions}
measures={view.measures}
dataSource={dataSource}
schema={view.schema}
fieldFeatures={fieldFeatures}
/>
</div>
);
})}
</div>
</div>
);
};

export default AssociationCharts;
64 changes: 64 additions & 0 deletions packages/frontend/src/pages/lts/association/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { toJS } from 'mobx';
import { observer } from 'mobx-react-lite';
import React from 'react';
import { FieldSummary } from '../../../service';
import { useGlobalStore } from '../../../store';
import Association from './assCharts';

const ObservableAssociation: React.FC = props => {
const { galleryStore, exploreStore } = useGlobalStore()
const { dataSource, insightSpaces, fields, assoListT1, assoListT2 } = exploreStore;
const { visualConfig } = galleryStore;

const fieldScores: FieldSummary[] = fields.map(f => {
const distribution = [...f.domain.entries()].map(c => ({
memberName: c[0],
count: c[1]
}))
return ({
fieldName: f.key,
distribution,
entropy: f.features.entropy,
maxEntropy: f.features.maxEntropy,
type: f.semanticType
})
})

const viewSpaces = insightSpaces.map((space, i) => ({
...space,
score: typeof space.score === 'number' ? space.score : 0,
index: i
}))

return <div>
asso content {assoListT1.length} + {assoListT2.length}
<Association
onSelectView={(index) => {
let pos = viewSpaces.findIndex((v) => v.index === index)
if (pos > -1) {
// galleryStore.goToPage(pos)
// tmpStore.
}
}}
dataSource={dataSource}
visualConfig={toJS(visualConfig)}
fieldScores={fieldScores}
vizList={assoListT2.slice(0, 5)}
/>
<Association
onSelectView={(index) => {
let pos = viewSpaces.findIndex((v) => v.index === index)
if (pos > -1) {
// galleryStore.goToPage(pos)
// tmpStore.
}
}}
dataSource={dataSource}
visualConfig={toJS(visualConfig)}
fieldScores={fieldScores}
vizList={assoListT1.slice(0, 5)}
/>
</div>
}

export default observer(ObservableAssociation);
80 changes: 16 additions & 64 deletions packages/frontend/src/pages/lts/index.tsx
Original file line number Diff line number Diff line change
@@ -1,70 +1,16 @@
import { makeAutoObservable, observable, runInAction } from 'mobx';
import { observer } from 'mobx-react-lite';
import { DefaultButton, PrimaryButton, Toggle, Stack } from 'office-ui-fabric-react';
import React, { useEffect, useState } from 'react';
import { useRef } from 'react';
import { IInsightSpace } from 'visual-insights/build/esm/insights/InsightFlow/interfaces';
import { ISpec } from 'visual-insights/build/esm/insights/InsightFlow/specification/encoding';
import { IRow } from '../../interfaces';
import { useGlobalStore } from '../../store';
import { LTSPipeLine } from '../../store/pipeLineStore/lts';
import BaseChart from '../../visBuilder/vegaBase';
import RadarChart from '../../components/radarChart';

class PageTMPStore {
public pageIndex: number = 0;
public aggState: boolean = false;
private ltsPipeLineStore: LTSPipeLine;
public spec: { schema: ISpec; dataView: IRow[] } | undefined = undefined;
public details: IInsightSpace[] = [];
constructor (ltsPipeLineStore: LTSPipeLine) {
makeAutoObservable(this, {
spec: observable.ref,
details: observable.ref
});
this.ltsPipeLineStore = ltsPipeLineStore;
}
public async emitViewChangeTransaction(index: number) {
// pipleLineStore统一提供校验逻辑
if (this.ltsPipeLineStore.insightSpaces && this.ltsPipeLineStore.insightSpaces.length > index) {
const spec = this.ltsPipeLineStore.specify(index);
if (spec) {
// this.spec = spec;
const agg = !spec.schema.geomType?.includes('point');
runInAction(() => {
this.spec = spec;
this.aggState = agg;
this.pageIndex = index;
this.details = []
})
}
}
}
public setAggState (aggState: boolean) {
this.aggState = aggState;
}
public async scanDetails (spaceIndex: number) {
const result = await this.ltsPipeLineStore.scanDetails(spaceIndex);
runInAction(() => {
this.details = result;
})
}
}

function useTMPStore (ltsPipeLineStore: LTSPipeLine) {
const storeRef = useRef<PageTMPStore>(new PageTMPStore(ltsPipeLineStore));
return storeRef.current;
}
import Ass from './association/index'

const LTSPage: React.FC = props => {
const { ltsPipeLineStore, dataSourceStore } = useGlobalStore();
const { ltsPipeLineStore, dataSourceStore, exploreStore } = useGlobalStore();
const { insightSpaces } = ltsPipeLineStore;
const tmpStore = useTMPStore(ltsPipeLineStore);

if (tmpStore === null) return null;

const { pageIndex, aggState, spec } = tmpStore;

const { pageIndex, aggState, spec, showAsso } = exploreStore;

return <div className="content-container">
<div className="card">
Expand All @@ -74,22 +20,22 @@ const LTSPage: React.FC = props => {
disabled={dataSourceStore.cleanedData.length === 0}
onClick={() => {
ltsPipeLineStore.startTask().then(() => {
tmpStore.emitViewChangeTransaction(0)
exploreStore.emitViewChangeTransaction(0)
})
}}
/>
<DefaultButton
style={{ marginLeft: "10px" }}
text="←"
onClick={() => {
tmpStore.emitViewChangeTransaction((pageIndex - 1 + insightSpaces.length) % insightSpaces.length)
exploreStore.emitViewChangeTransaction((pageIndex - 1 + insightSpaces.length) % insightSpaces.length)
}}
/>
<DefaultButton
style={{ marginLeft: "10px" }}
text="→"
onClick={() => {
tmpStore.emitViewChangeTransaction((pageIndex + 1) % insightSpaces.length)
exploreStore.emitViewChangeTransaction((pageIndex + 1) % insightSpaces.length)
}}
/>
</Stack>
Expand All @@ -99,7 +45,7 @@ const LTSPage: React.FC = props => {
offText="Off"
label="Default Aggregate"
onChange={(e, checked) => {
tmpStore.setAggState(Boolean(checked))
exploreStore.setAggState(Boolean(checked))
}}
/>
<h2>Visual Insights(v2 engine β)</h2>
Expand All @@ -123,11 +69,12 @@ const LTSPage: React.FC = props => {
</div>}
{
insightSpaces.length > 0 && spec && <div>
<PrimaryButton text="details" onClick={() => {tmpStore.scanDetails(pageIndex)}} />
<PrimaryButton text="details" onClick={() => {exploreStore.scanDetails(pageIndex)}} />
<PrimaryButton style={{ marginLeft: '1em' }} text="Associate" onClick={() => {exploreStore.getAssociatedViews()}} />
<div>
{
tmpStore.details.length > 0 && <RadarChart
dataSource={tmpStore.details}
exploreStore.details.length > 0 && <RadarChart
dataSource={exploreStore.details}
threshold={0.8}
keyField="type"
valueField="significance"
Expand All @@ -137,6 +84,11 @@ const LTSPage: React.FC = props => {
</div>
}
</div>
<div>
{
showAsso && <Ass />
}
</div>
</div>
</div>
</div>
Expand Down
Loading

0 comments on commit 284413a

Please sign in to comment.