1 | var _ = require("underscore");
|
2 | var DataLayer = require("./DataLayer");
|
3 | var helpers = require("../helpers");
|
4 |
|
5 |
|
6 |
|
7 | module.exports = DataLayer.extend("Neo4jLayer", {
|
8 |
|
9 | parseArguments: function(args){
|
10 | switch(args.length){
|
11 | case 0: return false;
|
12 | case 1:
|
13 | if(typeof args[0] !== "function") return false;
|
14 | else return [undefined,{},args[0]];
|
15 | case 2:
|
16 | if(typeof args[1] !== "function") return false;
|
17 | else return [args[0],{}, args[1]];
|
18 | case 3:
|
19 | if(typeof args[2] !== "function") return false;
|
20 | else return [args[0],args[1], args[2]];
|
21 | default: return false;
|
22 | }
|
23 | },
|
24 |
|
25 | parseOptions: function(data, options){
|
26 | if(!options.labels) options.labels = "";
|
27 | if(!data) options.properties = "";
|
28 | else{
|
29 | var properties = _.pick(data, _.without(this.publicFields || _.keys(this.fields), this.primaryKey));
|
30 | options.properties = "{"+_.keys(properties).map(function(prop){
|
31 | return [prop, ": ", "#", prop].join("");
|
32 | }).join(", ")+"}";
|
33 | }
|
34 | },
|
35 |
|
36 | formatResult: function(result){
|
37 | if(Array.isArray(result)) result = result.pop();
|
38 | return _.extend(result.data, _.object([[this.primaryKey, result.metadata.id]]));
|
39 | },
|
40 |
|
41 | create: function(obj, options, cb){
|
42 | var self = this;
|
43 | var properties = _.pick(obj, _.without(this.publicFields || _.keys(this.fields), this.primaryKey));
|
44 | if(_.keys(properties).length === 0) return cb("Error: empty object");
|
45 | this.query("CREATE (@nodeName@labels @properties) RETURN @nodeName", {values: properties, options: options}, function(err, result){
|
46 | if(err) return cb(err);
|
47 | cb(null, self.formatResult(result[0]));
|
48 | });
|
49 | },
|
50 |
|
51 | find: function(pattern, options, cb){
|
52 | var self = this;
|
53 | if(typeof pattern === "number" || typeof pattern === "string"){
|
54 | this.neo4j.Node.get(pattern).then(function(result){
|
55 | cb(null, self.formatResult(result));
|
56 | }).catch(function(err){cb(err);});
|
57 | }
|
58 | else if(Array.isArray(pattern) && _.every(pattern, function(p){return typeof p === "number" || typeof p === "string"})){
|
59 | this.query("MATCH (@nodeName@labels) WHERE ID(@nodeName) IN ["+this.neo4j.escape(pattern)+"] RETURN @nodeName", {values: false, options: options}, function(err, result){
|
60 | if(err) return cb(err);
|
61 | cb(null, result.map(function(r){return self.formatResult(r);}));
|
62 | });
|
63 | }
|
64 | else if(_.isObject(pattern)){
|
65 | var properties = _.pick(pattern, _.without(this.publicFields || _.keys(this.fields), this.primaryKey));
|
66 | if(_.keys(properties).length === 0) return cb(null, []);
|
67 | this.query("MATCH (@nodeName@labels) WHERE "+_.keys(properties).map(function(prop){
|
68 | if(Array.isArray(properties[prop])){
|
69 | return ["@nodeName", ".", prop, " IN ", "[", properties[prop].map(function(val){
|
70 | return self.neo4j.escape(val);
|
71 | }), "]"].join("");
|
72 | }
|
73 | return ["@nodeName", ".", prop, "=", "#", prop].join("");
|
74 | }).join(" AND ")+" RETURN @nodeName", {values: properties, options: options}, function(err, result){
|
75 | if(err) return cb(err);
|
76 | cb(null, result.map(function(r){return self.formatResult(r);}));
|
77 | });
|
78 | }
|
79 | else{
|
80 | this.query("MATCH (@nodeName@labels) RETURN @nodeName", {values: false, options: options}, function(err, result){
|
81 | if(err) return cb(err);
|
82 | cb(null, result.map(function(r){return self.formatResult(r);}));
|
83 | });
|
84 | }
|
85 | },
|
86 |
|
87 | findOne: function(pattern, options, cb){
|
88 |
|
89 | },
|
90 |
|
91 | update: function(pattern, options, cb){
|
92 |
|
93 | },
|
94 |
|
95 | delete: function(pattern, options, cb){
|
96 |
|
97 | },
|
98 |
|
99 |
|
100 | }, {
|
101 |
|
102 | setupDatabase: function(self, env, name){
|
103 | var Prototype = this;
|
104 | self.setupNode = function(cb){ Prototype.setupStore(self, env, function(err){
|
105 | if(err) return cb(err);
|
106 | env.i.do("log.sys", "DataLayer:neo4j", name);
|
107 | cb();
|
108 | }); }
|
109 | },
|
110 |
|
111 | setupStore: function(instance, env, cb){
|
112 | instance.neo4j = env.engines.neo4j;
|
113 | instance.query = function(query, data, cb){
|
114 | _.extend(data.options, {nodeName: instance.nodeName, debug: data.options.debug || this.options.debug });
|
115 | this.parseOptions(data.values, data.options);
|
116 | var query = this.neo4j.format(query, data, cb);
|
117 | if(query === false) return cb("Invalid query");
|
118 | if(data.options.debug){
|
119 | env.i.do("log.debug", ["[ Neo4j debug ]",
|
120 | [ " V V V V V V V V V V V V V V V V ","==============================================================================================>>>",
|
121 | data.options.debug,
|
122 | "Neo4j> "+query,
|
123 | "DATA> "+JSON.stringify(data.values),
|
124 | "==============================================================================================<<<",""
|
125 | ].join("\n")
|
126 | ]);
|
127 | delete data.options.debug;
|
128 | }
|
129 | this.neo4j.query(query, data.values).then(function(result){ cb(null, result.data); }).catch(cb);
|
130 | }
|
131 | cb();
|
132 | },
|
133 |
|
134 | extend: function(name, props, statics){
|
135 | this.setMethods(this.prototype, props);
|
136 | return DataLayer.extend.apply(this, arguments);
|
137 | }
|
138 | });
|