Skip to content

Commit 7d74fe9

Browse files
authored
Merge pull request #638 from GraphScope/chore-hover
feat: remove the `@graphscope/stduio-driver` from StudioGraph
2 parents 5482d21 + f8daf01 commit 7d74fe9

File tree

31 files changed

+376
-768
lines changed

31 files changed

+376
-768
lines changed
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import type {
2+
IServiceQueries,
3+
INeighborQueryData,
4+
INeighborQueryItems,
5+
IQueryStatement,
6+
} from '@graphscope/studio-graph';
7+
import { queryNeighborData, queryNeighborItems } from './queryNeighbor';
8+
import type { IQueryGraphData, IQueryGraphSchema } from '../../components/FetchGraph';
9+
import type { IQuerySearch } from '../../components/Searchbar';
10+
import type { IQuerySavedStatements } from '../../components/Searchbar/CascaderSearch';
11+
import type { IQueryStatistics } from '../../components/Statistics/TotalCounts';
12+
import type { IQueryPropertyStatics } from '../../components/Statistics/Properties/ChartView';
13+
import type { IQueryNeighborStatics } from '../../components/Next/Neighbors';
14+
15+
export type ExploreQueryTypes =
16+
| IQueryGraphData
17+
| IQueryGraphSchema
18+
| IQuerySearch
19+
| IQuerySavedStatements
20+
| IQueryStatistics
21+
| IQueryPropertyStatics
22+
| IQueryNeighborStatics
23+
| INeighborQueryData
24+
| INeighborQueryItems
25+
| IQueryStatement;
26+
27+
import { queryGraphSchema } from './queryGraphSchema';
28+
import { queryStatement } from './queryStatement';
29+
import { querySavedStaments } from './querySavedStatements';
30+
import { queryGraphData } from './queryGraphData';
31+
import { queryPropertyStatics } from './queryPropertyStatics';
32+
import { queryNeighborStatics } from './queryNeighborStatics';
33+
import { querySearch } from './querySearch';
34+
import { queryStatistics } from './queryStatistics';
35+
36+
const services: IServiceQueries<ExploreQueryTypes> = {
37+
queryNeighborData,
38+
queryNeighborItems,
39+
queryGraphSchema,
40+
queryStatement,
41+
querySavedStaments,
42+
queryGraphData,
43+
queryPropertyStatics,
44+
queryNeighborStatics,
45+
querySearch,
46+
queryStatistics,
47+
};
48+
export default services;
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import type { IQueryGraphData } from '../../components/FetchGraph/index';
2+
export const queryGraphData: IQueryGraphData['query'] = async () => {
3+
try {
4+
// const data = await queryStatement('Match a return a limit 100');
5+
// return data;
6+
return {
7+
nodes: [],
8+
edges: [],
9+
};
10+
} catch (error) {
11+
console.log('error', error);
12+
return {
13+
nodes: [],
14+
edges: [],
15+
};
16+
}
17+
};
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { Utils } from '@graphscope/studio-components';
2+
import { queryStatement } from './queryStatement';
3+
import { getQueryEngineType, transNeo4jSchema } from '../utils';
4+
5+
export const queryGraphSchema = async () => {
6+
try {
7+
const engine = getQueryEngineType();
8+
if (engine === 'neo4j') {
9+
const neo4jSchema = await queryStatement('CALL apoc.meta.schema');
10+
const schema = transNeo4jSchema(neo4jSchema.raw);
11+
return schema;
12+
}
13+
if (engine === 'kuzu_wasm') {
14+
return await queryStatement('CALL kuzu.meta.schema');
15+
}
16+
if (engine === 'graphscope') {
17+
const script = `call gs.procedure.meta.schema()`;
18+
const result = await queryStatement(script);
19+
const { schema } = result.table[0];
20+
const _schema = JSON.parse(schema);
21+
return Utils.transSchema(_schema);
22+
}
23+
return {
24+
nodes: [],
25+
edges: [],
26+
};
27+
} catch (error) {
28+
return { nodes: [], edges: [] };
29+
}
30+
};
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import type { INeighborQueryData, INeighborQueryItems } from '@graphscope/studio-graph';
2+
import { queryStatement } from './queryStatement';
3+
export const queryNeighborData: INeighborQueryData['query'] = async params => {
4+
const { key, selectIds } = params;
5+
const script = `
6+
MATCH ${key}
7+
WHERE elementId(a) IN [${selectIds}]
8+
RETURN a,b,c
9+
`;
10+
const data = await queryStatement(script);
11+
return data;
12+
};
13+
14+
export const queryNeighborItems: INeighborQueryItems['query'] = async params => {
15+
const { schema } = params;
16+
const itemMap = {};
17+
schema.nodes.forEach(node => {
18+
itemMap[node.label] = getOptionsBySchema(schema, node.label);
19+
});
20+
return itemMap;
21+
};
22+
23+
function getOptionsBySchema(schema, nodeLabel) {
24+
const options: { key: string; label: string }[] = [];
25+
schema.edges.forEach(item => {
26+
let direction = 'out';
27+
const { source, target, label } = item;
28+
const include = nodeLabel === source || nodeLabel === target;
29+
if (include && source === target) {
30+
direction = 'both';
31+
options.push({
32+
key: `(a:${source})-[b:${label}]-(c:${target})`,
33+
label: `[${label}]-(${target})`,
34+
});
35+
return;
36+
}
37+
if (source === nodeLabel) {
38+
direction = 'out';
39+
options.push({
40+
key: `(a:${source})-[b:${label}]->(c:${target})`,
41+
label: `[${label}]->(${target})`,
42+
});
43+
}
44+
if (target === nodeLabel) {
45+
direction = 'in';
46+
options.push({
47+
key: `(a:${source})<-[b:${label}]-(c:${target})`,
48+
label: `[${label}]<-(${target})`,
49+
});
50+
}
51+
});
52+
53+
const extraItems =
54+
options.length > 1
55+
? [
56+
{
57+
key: `(a)-[b]-(c)`,
58+
label: `All Neighbors`,
59+
},
60+
]
61+
: [];
62+
return [...extraItems, ...options];
63+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { queryStatement } from './queryStatement';
2+
export const queryNeighborStatics = async (property: string, selectIds: string[]) => {
3+
const data = await queryStatement(`
4+
MATCH(a)-[b]-(c)
5+
where a.${property} IS NOT NULL
6+
AND elementId(a) IN [${selectIds}]
7+
return c.${property},COUNT(c.${property}) as counts
8+
`);
9+
return data.table;
10+
};
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { queryStatement } from './queryStatement';
2+
export const queryPropertyStatics = async (property: string) => {
3+
const data = await queryStatement(`
4+
MATCH(a) where a.${property} IS NOT NULL
5+
WITH a.${property} AS ${property}
6+
return ${property},COUNT(${property}) as counts
7+
`);
8+
9+
return data.table;
10+
};
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import localforage from 'localforage';
2+
3+
const DB_QUERY_SAVED = localforage.createInstance({
4+
name: 'DB_QUERY_SAVED',
5+
});
6+
export const querySavedStaments = async () => {
7+
const result: any[] = [];
8+
await DB_QUERY_SAVED.iterate(item => {
9+
if (item) {
10+
result.push(item);
11+
}
12+
});
13+
return result;
14+
};
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { queryStatement } from './queryStatement';
2+
export const querySearch = async params => {
3+
const { config, value } = params;
4+
const { value: type } = config.find(item => item.type === 'type') || { value: null };
5+
const { value: label } = config.find(item => item.type === 'label') || { value: null };
6+
const { value: property } = config.find(item => item.type === 'property') || { value: null };
7+
8+
// 精确模糊搜索
9+
10+
if (type === 'Vertex') {
11+
if (label && !property) {
12+
return queryStatement(`match (n:${label}) return n`);
13+
}
14+
if (label && property) {
15+
if (value) {
16+
return queryStatement(`match (n:${label}) where n.${property} CONTAINS "${value}" return n`);
17+
} else {
18+
return queryStatement(`match (n:${label}) where n.${property} IS NOT NULL return n`);
19+
}
20+
}
21+
if (!label && property) {
22+
if (value) {
23+
return queryStatement(`match (n) where n.${property} CONTAINS "${value}" return n`);
24+
} else {
25+
return queryStatement(`match (n) where n.${property} IS NOT NULL return n`);
26+
}
27+
}
28+
}
29+
if (type === 'Edge') {
30+
if (label && !property) {
31+
return queryStatement(`match (a)-[r:${label}]->(b) return a,r,b`);
32+
}
33+
if (label && property) {
34+
if (value) {
35+
return queryStatement(`match (a)-[r:${label}]->(b) where r.${property} CONTAINS "${value}" return a,r,b`);
36+
} else {
37+
return queryStatement(`match (a)-[r:${label}]->(b) where r.${property} IS NOT NULL return a,r,b`);
38+
}
39+
}
40+
if (!label && property) {
41+
if (value) {
42+
return queryStatement(`match (a)-[r]->(b) where r.${property} CONTAINS "${value}" return a,r,b`);
43+
} else {
44+
return queryStatement(`match (a)-[r]->(b) where r.${property} IS NOT NULL return a,r,b`);
45+
}
46+
}
47+
}
48+
49+
return {
50+
nodes: [],
51+
edges: [],
52+
};
53+
};
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { queryGraph } from '@graphscope/studio-driver';
2+
import { Utils } from '@graphscope/studio-components';
3+
import type { IQueryStatement } from '@graphscope/studio-graph';
4+
import { getQueryEngineType, transNeo4jSchema } from '../utils';
5+
import { getDriver } from '../kuzu-wasm';
6+
const { storage } = Utils;
7+
export const queryStatement: IQueryStatement['query'] = async (script: string) => {
8+
const query_language = storage.get<'cypher' | 'gremlin'>('query_language') || 'cypher';
9+
const query_endpoint = storage.get<string>('query_endpoint') || '';
10+
const query_initiation = storage.get<'Server' | 'Browser'>('query_initiation');
11+
const query_username = storage.get<string>('query_username');
12+
const query_password = storage.get<string>('query_password');
13+
try {
14+
const engine = getQueryEngineType();
15+
if (engine === 'graphscope' || engine === 'neo4j') {
16+
const _params = {
17+
script,
18+
language: query_language,
19+
endpoint: query_endpoint,
20+
username: query_username,
21+
password: query_password,
22+
};
23+
24+
if (query_initiation === 'Server') {
25+
return await fetch('/graph/query', {
26+
method: 'POST',
27+
headers: {
28+
'Content-Type': 'application/json',
29+
},
30+
body: JSON.stringify(_params),
31+
})
32+
.then(res => res.json())
33+
.then(res => {
34+
if (res.success) {
35+
return res.data;
36+
}
37+
return {
38+
nodes: [],
39+
edges: [],
40+
};
41+
});
42+
}
43+
return queryGraph(_params);
44+
}
45+
if (engine === 'kuzu_wasm') {
46+
const driver = await getDriver();
47+
return await driver.queryData(script);
48+
}
49+
} catch (error) {
50+
return {
51+
nodes: [],
52+
edges: [],
53+
};
54+
}
55+
};
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { queryStatement } from './queryStatement';
2+
export const queryStatistics = async () => {
3+
try {
4+
// const script = `call gs.procedure.meta.statistics()`;
5+
// const result = await queryStatement(script);
6+
// debugger;
7+
// console.log('result', result, result.raw.records[0]._fields[0]);
8+
// return JSON.parse(result.raw.records[0]._fields[0]);
9+
10+
// 临时方案
11+
const countNodes = await queryStatement('MATCH (n) RETURN count(n)');
12+
const countEdges = await queryStatement('MATCH (a)-[r]-(b) RETURN count(r)');
13+
14+
return {
15+
total_vertex_count: countNodes.raw.records[0]._fields[0].toNumber(),
16+
total_edge_count: countEdges.raw.records[0]._fields[0].toNumber(),
17+
};
18+
} catch (error) {
19+
return {
20+
total_vertex_count: 0,
21+
total_edge_count: 0,
22+
};
23+
}
24+
};

0 commit comments

Comments
 (0)