view src/app/query.service.js @ 58:3b4046e0cc02 default

Merge from ng2-table branch. d7c947909ab888c013171b8c037e4f9fab30fe57
author casties
date Wed, 29 Mar 2017 17:19:12 +0200
parents
children 7b9d616695d3
line wrap: on
line source

"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var core_1 = require('@angular/core');
var http_1 = require('@angular/http');
require('rxjs/Rx'); // import all RxJS operators
//import 'rxjs/add/operator/map';
var app_config_1 = require('./app-config');
var query_mode_1 = require('./query-mode');
var query_state_1 = require('./query-state');
var result_type_1 = require('./result-type');
var ismi_result_types_1 = require('./ismi-result-types');
var ismi_relation_types_1 = require('./ismi-relation-types');
var QueryService = (function () {
    function QueryService(_http) {
        this._http = _http;
        this.typeAttribute = '_type';
        this.excludedAttributes = {};
        // init query state
        this.state = new query_state_1.QueryState();
    }
    QueryService.prototype.setup = function (newStateString) {
        // get list of object types
        this.setupObjectTypes();
        // get state from string
        if (newStateString) {
            this.state.setStateFromString(newStateString);
        }
    };
    QueryService.prototype.getState = function () {
        return this.state;
    };
    QueryService.prototype.getQueryModes = function (index) {
        if (index == 0) {
            return query_mode_1.FIRST_QUERY_MODES;
        }
        else {
            return query_mode_1.QUERY_MODES;
        }
    };
    /**
     * return the first set of options for the given query mode.
     */
    QueryService.prototype.getQueryOptions = function (queryMode) {
        var options = [];
        if (queryMode == null)
            return options;
        if (queryMode.id === 'type_is') {
            options = this.objectTypes;
        }
        else if (queryMode.id === 'relation_is') {
            options = this.state.resultRelations;
        }
        else if (queryMode.id === 'att_contains') {
            options = this.filterAttributes(this.state.resultAttributes);
        }
        else if (queryMode.id === 'att_contains_norm') {
            options = this.filterAttributes(this.state.resultAttributes, true);
        }
        else if (queryMode.id === 'att_num_range') {
            options = this.filterAttributes(this.state.resultAttributes);
        }
        console.debug("getQueryOptions returns: ", options);
        return options;
    };
    /**
     * fetch all object types from Neo4j and store in this.objectTypes.
     */
    QueryService.prototype.setupObjectTypes = function () {
        var _this = this;
        var query = "MATCH (n) WITH DISTINCT labels(n) AS labels\n                UNWIND labels AS label \n                RETURN DISTINCT label ORDER BY label";
        var res = this.fetchCypherResults([query]);
        res.subscribe(function (data) {
            console.debug("neo4j data=", data);
            _this.objectTypes = data.results[0].data
                .map(function (elem) { return elem.row[0]; })
                .filter(function (elem) { return elem[0] != "_"; });
            console.debug("object types=", _this.objectTypes);
        }, function (err) { return console.error("neo4j error=", err); }, function () { return console.debug('neo4j query Complete'); });
    };
    /**
     * Set the query step at index.
     */
    QueryService.prototype.setQueryStep = function (index, step) {
        this.state.steps[index] = step;
    };
    /**
     * Create the cypher queries for the current query state.
     *
     * Updates the queries for results, attributes and relations.
     */
    QueryService.prototype.createCypherQuery = function () {
        var queryMatch = '';
        var queryWhere = '';
        var queryReturn = '';
        var queryParams = {};
        var resultQuery = '';
        var attributesQuery = '';
        var outRelsQuery = '';
        var inRelsQuery = '';
        var returnType = '';
        var nIdx = 1;
        this.state.steps.forEach(function (step, stepIdx) {
            var mode = step.mode.id;
            var params = step.params;
            /*
             * step: object type is
             */
            if (mode === 'type_is') {
                queryMatch = "MATCH (n" + nIdx + ":" + params.objectType + ")";
                queryWhere = '';
                queryReturn = "RETURN n" + nIdx;
                returnType = 'node';
            }
            /*
             * step: object id is
             */
            if (mode === 'id_is') {
                if (!queryMatch) {
                    // first step - use match clause
                    queryMatch = "MATCH (n" + nIdx + " {ismi_id: {att_val" + stepIdx + "}})";
                    queryParams[("att_val" + stepIdx)] = parseInt(params.value, 10);
                    queryWhere = '';
                    queryReturn = "RETURN n" + nIdx;
                    returnType = 'node';
                }
                else {
                    // use where clause
                    if (!queryWhere) {
                        queryWhere = 'WHERE ';
                    }
                    else {
                        queryWhere += ' AND ';
                    }
                    queryWhere += "n" + nIdx + ".ismi_id = {att_val" + stepIdx + "}";
                    queryParams[("att_val" + stepIdx)] = parseInt(params.value, 10);
                }
            }
            /*
             * step: relation type is
             */
            if (mode === 'relation_is') {
                nIdx += 1;
                var rel = params.relationType;
                if (rel.isOutgoing()) {
                    queryMatch += "-[:`" + rel.getRelType() + "`]->(n" + nIdx + ")";
                }
                else {
                    // inverse relation
                    queryMatch += "<-[:`" + rel.getRelType() + "`]-(n" + nIdx + ")";
                }
                queryReturn = "RETURN DISTINCT n" + nIdx;
                returnType = 'node';
            }
            /*
             * step: attribute contains(_norm)
             */
            if (mode === 'att_contains' || mode === 'att_contains_norm') {
                if (!queryWhere) {
                    queryWhere = 'WHERE ';
                }
                else {
                    queryWhere += ' AND ';
                }
                if (params.attribute === 'ismi_id') {
                    // ismi_id is integer
                    queryWhere += "n" + nIdx + ".ismi_id = {att_val" + stepIdx + "}";
                    queryParams[("att_val" + stepIdx)] = parseInt(params.value, 10);
                }
                else {
                    if (mode === 'att_contains_norm') {
                        // match _n_attribute with normValue
                        queryWhere += "lower(n" + nIdx + "._n_" + params.attribute + ") CONTAINS lower({att_val" + stepIdx + "})";
                        queryParams[("att_val" + stepIdx)] = params.normValue;
                    }
                    else {
                        queryWhere += "lower(n" + nIdx + "." + params.attribute + ") CONTAINS lower({att_val" + stepIdx + "})";
                        queryParams[("att_val" + stepIdx)] = params.value;
                    }
                }
            }
            /*
             * step: attribute number range
             */
            if (mode === 'att_num_range') {
                if (!queryWhere) {
                    queryWhere = 'WHERE ';
                }
                else {
                    queryWhere += ' AND ';
                }
                queryWhere += ("toint(n" + nIdx + "." + params.attribute + ") >= toint({att_nlo" + stepIdx + "})")
                    + (" AND toint(n" + nIdx + "." + params.attribute + ") <= toint({att_nhi" + stepIdx + "})");
                queryParams[("att_nlo" + stepIdx)] = params.numLo;
                queryParams[("att_nhi" + stepIdx)] = params.numHi;
            }
        });
        // compose query
        resultQuery = queryMatch + (queryWhere ? '\n' + queryWhere : '') + '\n' + queryReturn;
        // compose query for attributes of result
        attributesQuery = queryMatch + ' ' + queryWhere + (" WITH DISTINCT keys(n" + nIdx + ") AS atts")
            + " UNWIND atts AS att RETURN DISTINCT att ORDER BY att";
        // compose query for relations of result
        outRelsQuery = queryMatch + '-[r]->() ' + queryWhere + ' RETURN DISTINCT type(r)';
        inRelsQuery = queryMatch + '<-[r]-() ' + queryWhere + ' RETURN DISTINCT type(r)';
        this.state.resultCypherQuery = resultQuery;
        this.state.cypherQueryParams = queryParams;
        this.state.attributesCypherQuery = attributesQuery;
        this.state.outRelsCypherQuery = outRelsQuery;
        this.state.inRelsCypherQuery = inRelsQuery;
        this.state.resultTypes = returnType;
    };
    /**
     * Create and run the cypher queries for the current query state.
     *
     * Updates the results and nextQuery attributes and relations.
     */
    QueryService.prototype.runQuery = function () {
        var _this = this;
        this.createCypherQuery();
        this.state.resultInfo = 'loading...';
        /*
         * run query for result table
         */
        var queries = [this.state.resultCypherQuery];
        var params = [this.state.cypherQueryParams];
        if (this.state.attributesCypherQuery) {
            queries.push(this.state.attributesCypherQuery);
            params.push(this.state.cypherQueryParams);
        }
        if (this.state.outRelsCypherQuery) {
            queries.push(this.state.outRelsCypherQuery);
            params.push(this.state.cypherQueryParams);
        }
        if (this.state.inRelsCypherQuery) {
            queries.push(this.state.inRelsCypherQuery);
            params.push(this.state.cypherQueryParams);
        }
        var res = this.fetchCypherResults(queries, params);
        res.subscribe(function (data) {
            console.debug("neo4j result data=", data);
            var resIdx = 0;
            /*
             * results for result table
             */
            _this.state.results = data.results[resIdx].data.map(function (elem) { return elem.row[0]; });
            _this.state.numResults = _this.state.results.length;
            // count all types
            var resTypes = {};
            _this.state.results.forEach(function (r) {
                var t = r[_this.typeAttribute];
                if (resTypes[t] == null) {
                    resTypes[t] = 1;
                }
                else {
                    resTypes[t] += 1;
                }
            });
            var info = '';
            for (var t in resTypes) {
                info += t + '(' + resTypes[t] + ') ';
            }
            info = info.substr(0, info.length - 1);
            _this.state.resultInfo = info;
            // save info also in last step
            _this.state.steps[_this.state.steps.length - 1].resultInfo = info;
            /*
             * results for attribute list
             */
            if (_this.state.attributesCypherQuery) {
                resIdx += 1;
                var atts = data.results[resIdx].data.map(function (elem) { return elem.row[0]; });
                _this.state.resultAttributes = atts;
                // the following assumes only one type in the result
                for (var t in resTypes) {
                    _this.state.resultType = result_type_1.getResultType(t, ismi_result_types_1.ISMI_RESULT_TYPES);
                    break;
                }
                _this.state.resultColumns = _this.state.resultType.getColumns(atts);
            }
            /*
             * results for relations list
             */
            if (_this.state.outRelsCypherQuery) {
                // outgoing aka forward relations
                resIdx += 1;
                var rels = data.results[resIdx].data.map(function (elem) { return elem.row[0]; })
                    .filter(function (elem) { return elem[0] != "_"; })
                    .map(function (elem) { return ismi_relation_types_1.getRelationType(elem, true); });
                _this.state.resultRelations = rels;
            }
            if (_this.state.inRelsCypherQuery) {
                // incoming aka reverse relations
                resIdx += 1;
                var rels = data.results[resIdx].data.map(function (elem) { return elem.row[0]; })
                    .filter(function (elem) { return elem[0] != "_"; })
                    .map(function (elem) { return ismi_relation_types_1.getRelationType(elem, false); });
                _this.state.resultRelations = _this.state.resultRelations.concat(rels);
            }
        }, function (err) { return console.error("neo4j result error=", err); }, function () { return console.debug('neo4j result query Complete'); });
    };
    QueryService.prototype.filterAttributes = function (attributes, normalized) {
        var _this = this;
        if (normalized === void 0) { normalized = false; }
        var atts = [];
        if (normalized) {
            attributes.forEach(function (att) {
                if (att.substr(0, 3) == "_n_") {
                    atts.push(att.substr(3));
                }
            });
        }
        else {
            atts = attributes.filter(function (elem) { return elem[0] != "_" && !_this.excludedAttributes[elem]; });
        }
        return atts;
    };
    /**
     * Run the given queries on the Neo4J server.
     *
     * Returns an Observable with the results.
     */
    QueryService.prototype.fetchCypherResults = function (queries, params) {
        if (params === void 0) { params = [{}]; }
        console.debug("fetching cypher queries: ", queries);
        var headers = new http_1.Headers();
        var auth = app_config_1.NEO4J_AUTHENTICATION;
        headers.append('Authorization', 'Basic ' + btoa(auth.user + ":" + auth.password));
        headers.append('Content-Type', 'application/json');
        headers.append('Accept', 'application/json');
        // put headers in options
        var opts = { 'headers': headers };
        // unpack queries into statements
        var statements = queries.map(function (q, i) {
            return { 'statement': q, 'parameters': (params[i]) ? params[i] : {} };
        });
        // create POST data from query
        var data = JSON.stringify({ 'statements': statements });
        // make post request asynchronously
        var resp = this._http.post(app_config_1.NEO4J_BASE_URL + '/transaction/commit', data, opts)
            .map(function (res) { return res.json(); });
        // return Observable
        return resp;
    };
    QueryService = __decorate([
        core_1.Injectable(), 
        __metadata('design:paramtypes', [http_1.Http])
    ], QueryService);
    return QueryService;
}());
exports.QueryService = QueryService;
//# sourceMappingURL=query.service.js.map