diff app/query.service.ts @ 11:6989cd00e8d7

relations work now as well as longer queries.
author Robert Casties <casties@mpiwg-berlin.mpg.de>
date Wed, 20 Jan 2016 19:49:10 +0100
parents 66dce99cef4e
children 1843b12eff9a
line wrap: on
line diff
--- 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 = {}) {