# HG changeset patch # User Robert Casties # Date 1453315750 -3600 # Node ID 6989cd00e8d70e5848b1d6d2b98db0ff1749a40f # Parent 66dce99cef4e008b0acdb51ce310761b01d70e7d relations work now as well as longer queries. diff -r 66dce99cef4e -r 6989cd00e8d7 app/query-mode.ts --- a/app/query-mode.ts Wed Jan 20 17:02:00 2016 +0100 +++ b/app/query-mode.ts Wed Jan 20 19:49:10 2016 +0100 @@ -1,4 +1,12 @@ export interface QueryMode { id: string; label: string; -} \ No newline at end of file +} + +export var QUERY_MODES: QueryMode[] = [ + {id: 'type_is', label:'Object type is'}, + {id: 'att_contains', label: 'Attribute'}, + {id: 'att_contains_norm', label: 'Attribute (normalized)'}, + {id: 'relation_is', label: 'Relation type is'} +]; + diff -r 66dce99cef4e -r 6989cd00e8d7 app/query-result.component.ts --- a/app/query-result.component.ts Wed Jan 20 17:02:00 2016 +0100 +++ b/app/query-result.component.ts Wed Jan 20 19:49:10 2016 +0100 @@ -8,8 +8,8 @@ selector: 'query-result', template: `
-

Cypher: {{queryState.cypherQuery}}

-

Query results ({{queryState.numResults}}):

+
{{queryState.resultCypherQuery}}
+

Query results ({{queryState.resultInfo}}):

diff -r 66dce99cef4e -r 6989cd00e8d7 app/query-select.component.ts --- a/app/query-select.component.ts Wed Jan 20 17:02:00 2016 +0100 +++ b/app/query-select.component.ts Wed Jan 20 19:49:10 2016 +0100 @@ -9,8 +9,8 @@ @Component({ selector: 'query-select', template: ` -
-
+
+ - + + + - - - contains - + + + contains + - -
+ +
`, inputs: ['index'] //outputs: ['queryChanged'] // this should work but doesn't @@ -77,21 +79,34 @@ onSelectOption(event: any) { var selected = event.target.value; console.debug("selected option:", selected); - var step = {'mode': this.selectedMode, 'objectType': selected}; - this._queryService.setQueryStep(this.index, step); - this.queryChanged.emit(this._queryService.getState()); + this.selectedOption = selected; + this.onSubmit(); } onSubmit() { console.debug("Submit! selectedMode=", this.selectedMode, " selectedOption=", this.selectedOption, " queryInput=", this.queryInput); - if (this.selectedMode.id == 'att_contains') { + var step: QueryStep; + if (this.selectedMode.id == 'type_is') { + var opt = this.selectedOption; + if (opt) { + step = {'mode': this.selectedMode, 'objectType': opt}; + } + } else if (this.selectedMode.id == 'relation_is') { + var opt = this.selectedOption; + if (opt) { + step = {'mode': this.selectedMode, 'relationType': opt}; + } + } else if (this.selectedMode.id == 'att_contains' || this.selectedMode.id == 'att_contains_norm') { var att = this.selectedOption; var val = this.queryInput; if (att && val) { - var step = {'mode': this.selectedMode, 'attribute': att, 'value': val}; - this._queryService.setQueryStep(this.index, step); - this.queryChanged.emit(this._queryService.getState()); + step = {'mode': this.selectedMode, 'attribute': att, 'value': val}; } } + + if (step != null) { + this._queryService.setQueryStep(this.index, step); + this.queryChanged.emit(this._queryService.getState()); + } } } diff -r 66dce99cef4e -r 6989cd00e8d7 app/query.service.ts --- a/app/query.service.ts Wed Jan 20 17:02:00 2016 +0100 +++ b/app/query.service.ts Wed Jan 20 19:49:10 2016 +0100 @@ -3,7 +3,7 @@ import 'rxjs/Rx'; // import all RxJS operators -import {QueryMode} from './query-mode'; +import {QueryMode, QUERY_MODES} from './query-mode'; import {QueryState} from './query-state'; import {QueryStep} from './query-step'; @@ -14,19 +14,17 @@ public state: QueryState; public ismiObjectTypes: any; - public QUERY_MODES: QueryMode[] = [ - {id: 'type_is', label:'Object type is'}, - {id: 'att_contains', label: 'Attribute'}]; - constructor(private _http: Http) { this.state = { 'steps': [], 'resultCypherQuery': '', - 'resultCypherParams': {}, - 'attributeCypherQuery': '', + 'cypherQueryParams': {}, + 'attributesCypherQuery': '', + 'relationsCypherQuery': '', 'results': [], 'resultTypes': '', - 'numResults': 0 + 'numResults': 0, + 'resultInfo': '' }; } @@ -39,15 +37,19 @@ } getQueryModes(): QueryMode[] { - return this.QUERY_MODES; + return QUERY_MODES; } getQueryOptions(queryMode: QueryMode) { var options = ['a1', 'b1', 'c1']; - if (queryMode.id === 'att_contains') { + if (queryMode.id === 'type_is') { + options = this.ismiObjectTypes; + } else if (queryMode.id === 'relation_is') { + options = this.state.nextQueryRelations; + } else if (queryMode.id === 'att_contains') { options = this.state.nextQueryAttributes; - } else if (queryMode.id === 'type_is') { - options = this.ismiObjectTypes; + } else if (queryMode.id === 'att_contains_norm') { + options = this.state.nextQueryAttributes; } console.debug("getQueryOptions returns: ", options); return options; @@ -79,30 +81,58 @@ var queryMatch = ''; var queryWhere = ''; var queryReturn = ''; + var queryParams = {}; var resultQuery = ''; - var attQuery = ''; + var attributesQuery = ''; + var relationsQuery = ''; var returnType = ''; - this.state.steps.forEach((step) => { + var nIdx = 1; + this.state.steps.forEach((step, stepIdx) => { // object type is if (step.mode.id === 'type_is') { - queryMatch = `MATCH (n:${step.objectType})`; + queryMatch = `MATCH (n${nIdx}:${step.objectType})`; queryWhere = ''; - queryReturn = 'RETURN n'; + queryReturn = `RETURN n${nIdx}`; + returnType = 'node'; + } + + // relation type is + if (step.mode.id === 'relation_is') { + nIdx += 1; + queryMatch += `-[:\`${step.relationType}\`]->(n${nIdx})`; + queryReturn = `RETURN n${nIdx}`; returnType = 'node'; } // attribute contains if (step.mode.id === 'att_contains') { - queryWhere = `WHERE lower(n.${step.attribute}) CONTAINS lower('${step.value}')`; - queryReturn = 'RETURN n'; - returnType = 'node'; + if (!queryWhere) { + queryWhere = 'WHERE '; + } else { + queryWhere += ' AND '; + } + queryWhere += `lower(n${nIdx}.${step.attribute}) CONTAINS lower({att_val${stepIdx}})`; + queryParams[`att_val${stepIdx}`] = step.value; + } + + // attribute contains (normalized) + if (step.mode.id === 'att_contains_norm') { + if (!queryWhere) { + queryWhere = 'WHERE '; + } else { + queryWhere += ' AND '; + } + queryWhere += `lower(n${nIdx}._n_${step.attribute}) CONTAINS lower('${step.value}')`; } }); - resultQuery = queryMatch + ' ' + queryWhere + ' ' + queryReturn; - attQuery = queryMatch + ' ' + queryWhere + ' WITH DISTINCT keys(n) AS atts UNWIND atts AS att RETURN DISTINCT att ORDER BY att'; + resultQuery = queryMatch + '\n' + queryWhere + '\n' + queryReturn; + attributesQuery = queryMatch + ' ' + queryWhere + ` WITH DISTINCT keys(n${nIdx}) AS atts UNWIND atts AS att RETURN DISTINCT att ORDER BY att`; + relationsQuery = queryMatch + '-[r]-() ' + queryWhere + ' RETURN DISTINCT type(r)'; this.state.resultCypherQuery = resultQuery; - this.state.attributeCypherQuery = attQuery; + this.state.cypherQueryParams = queryParams; + this.state.attributesCypherQuery = attributesQuery; + this.state.relationsCypherQuery = relationsQuery; this.state.resultTypes = returnType; } @@ -110,20 +140,34 @@ this.createCypherQuery(); // run query for result table var resQuery = this.state.resultCypherQuery; - var resParams = this.state.cypherParams; - var resRes = this.fetchCypherResult(resQuery, resParams); + var queryParams = this.state.cypherQueryParams; + var resRes = this.fetchCypherResult(resQuery, queryParams); resRes.subscribe( data => { console.debug("neo4j result data=", data); this.state.results = data.results[0].data.map(elem => elem.row[0]); this.state.numResults = this.state.results.length; + // count all types + var resTypes = {}; + this.state.results.forEach((r) => { + if (resTypes[r.type] == null) { + resTypes[r.type] = 1; + } else { + resTypes[r.type] += 1; + } + }); + var info = ''; + for (var t in resTypes) { + info += t + '(' + resTypes[t] + ') '; + } + this.state.resultInfo = info; }, err => console.error("neo4j result error=", err), () => console.debug('neo4j result query Complete') ); // run query for attribute list - if (this.state.attributeCypherQuery) { - var attRes = this.fetchCypherResult(this.state.attributeCypherQuery); + if (this.state.attributesCypherQuery) { + var attRes = this.fetchCypherResult(this.state.attributesCypherQuery, queryParams); attRes.subscribe( data => { console.debug("neo4j att data=", data); @@ -133,6 +177,18 @@ () => console.debug('neo4j att query Complete') ); } + // run query for relations list + if (this.state.relationsCypherQuery) { + var attRes = this.fetchCypherResult(this.state.relationsCypherQuery, queryParams); + attRes.subscribe( + data => { + console.debug("neo4j rel data=", data); + this.state.nextQueryRelations = data.results[0].data.map(elem => elem.row[0]).filter(elem => elem[0] != "_");; + }, + err => console.error("neo4j rel error=", err), + () => console.debug('neo4j rel query Complete') + ); + } } fetchCypherResult(query: string, params = {}) {
Type