Comparing version 0.1.10 to 0.2.0
@@ -0,1 +1,18 @@ | ||
## TODO (upcoming releases) | ||
- Option to not use Transaction to do CUD (ie No need for commit()). eg. g.addVertex().then(); Batch kibble will not required for these calls | ||
- Client version initialised with var g = require('grex'); | ||
- Test CUD | ||
## 0.2.0 | ||
- get() call removed | ||
- rollback() removed | ||
- Enable multiple connections (multiple users) in Node module | ||
- New Transaction process for CUD. Must create transaction object and invoke cud methods. Includes better error trapping. | ||
- Transaction success no longer requires testing for success = true || false. Only successful values are returned to success callback. All errors sent to error callback. | ||
- Removed version and querytime from returned results | ||
- Complies with Blueprints 2.4.0 | ||
- Add Contains.IN and Contains.NOT_IN | ||
- Data Type preservation | ||
## 0.1.10 | ||
@@ -2,0 +19,0 @@ |
@@ -1,23 +0,23 @@ | ||
var g = require('../grex.js'); | ||
var grex = require('../src/grex.js'); | ||
var t1, t2; | ||
var trxn; | ||
t1 = g.addVertex({name:'Test1a'}); | ||
t2 = g.addVertex({name:'Test2a'}); | ||
g.addEdge(t1, t2, 'linked', {name:"ALabel"}) | ||
grex.connect().then(function(g){ | ||
t1 = g.addVertex({name:'Test1b'}); | ||
t2 = g.addVertex({name:'Test2b'}); | ||
g.addEdge(t2, t1, 'linked', {name:"BLabel"}) | ||
trxn = g.begin(); | ||
g.commit() | ||
.then(function(result){ | ||
if (result) { | ||
if (result.success == false) { | ||
console.error("Failed to add vertices."); | ||
} else { | ||
console.log("Added new vertices successfully. -> ", result); | ||
} | ||
} | ||
}, function(err) { | ||
console.error(err) | ||
t1 = trxn.addVertex(111,{name:'Test1a'}); | ||
t2 = trxn.addVertex(222,{name:'Test2a'}); | ||
trxn.addEdge(111, 222, 'linked', {name:"ALabel"}) | ||
// t1 = trxn.addVertex({name:'Test1b'}); | ||
// t2 = trxn.addVertex({name:'Test2b'}); | ||
// trxn.addEdge(t2, t1, 'linked', {name:"BLabel"}) | ||
trxn.commit().then(function(result){ | ||
console.log("Added new vertices successfully. -> ", result); | ||
}, function(err) { | ||
console.error(err) | ||
}); | ||
}); |
@@ -1,36 +0,22 @@ | ||
var g = require('grex'); | ||
var g = require('../src/grex.js'); | ||
var y = "bob"; | ||
g.addVertex(0, {name:y}); | ||
g.commit() | ||
.then(function(result){ | ||
if (result) { | ||
if (result.success == false) { | ||
console.log("Failed to add vertex for", y); | ||
} else { | ||
console.log("Added a vertex successfully for", y); | ||
g.createIndex("actor", "Vertex.class").get() | ||
.then(function(result){ | ||
if (result) { | ||
if (result.success == false) { | ||
console.log("Failed to create index - actor"); | ||
} else { | ||
g.idx('actor').put('name', y, g.v(0)).get() | ||
.then(function(result){ | ||
if (result) { | ||
if (result.success == false) { | ||
console.log("Failed to add an index for", y); | ||
} else { | ||
console.log("Index added successfully for", y); | ||
} | ||
} | ||
}, function(err) { | ||
console.log(err) | ||
}); | ||
} | ||
} | ||
var trxn = g.begin(); | ||
var vertex = trxn.addVertex({name:y}); | ||
trxn.commit().then | ||
(function(result) { | ||
console.log("Added a vertex successfully for", y); | ||
g.createIndex('actor', 'Vertex.class').then | ||
(function(result){ | ||
g.idx('actor').put('name', y, g.v(vertex._id)).then | ||
(function(result){ | ||
console.log("Index added successfully for", y); | ||
}, function(err) { | ||
console.log(err) | ||
}); | ||
}, function(err) { | ||
console.log(err) | ||
}); | ||
} | ||
} | ||
}, function(err) { | ||
console.log(err) | ||
}); | ||
}, function(err) { | ||
console.log(err) | ||
}); |
{ | ||
"name": "grex", | ||
"description": "Client for Rexster Graph Server", | ||
"version": "0.1.10", | ||
"keywords": ["database", "graph", "tinkerpop", "rexster", "gremlin", "blueprints"], | ||
"version": "0.2.0", | ||
"keywords": [ | ||
"database", | ||
"graph", | ||
"tinkerpop", | ||
"rexster", | ||
"gremlin", | ||
"blueprints" | ||
], | ||
"homepage": "https://github.com/entrendipity/grex", | ||
"authors": ["Frank Panetta <frank.panetta@entrendipity.com.au>"], | ||
"authors": [ | ||
"Frank Panetta <frank.panetta@entrendipity.com.au>" | ||
], | ||
"repository": { | ||
@@ -19,3 +28,12 @@ "type": "git", | ||
}, | ||
"main": "grex.js" | ||
"main": "./index.js", | ||
"devDependencies": { | ||
"grunt": "~0.4.1", | ||
"grunt-contrib-uglify": "~0.2.2", | ||
"grunt-contrib-jshint": "~0.6.0", | ||
"grunt-browserify": "~1.2.1", | ||
"grunt-mocha": "~0.4.0", | ||
"grunt-mocha-test": "~0.6.2", | ||
"grunt-browserify2": "~0.1.8" | ||
} | ||
} |
222
README.md
@@ -24,10 +24,9 @@ gRex | ||
## Installation | ||
## Usage | ||
gRex can be loaded as: | ||
- a ``<script>`` tag in the browser (creating a ``g`` global variable). Files are located in the browser directory. | ||
- a ``<script>`` tag in the browser. Files are located in the browser directory. | ||
``` | ||
<script type="text/javascript" src="q.min.js"></script> | ||
<script type="text/javascript" src="grex.min.js"></script> | ||
@@ -38,7 +37,7 @@ ``` | ||
```bash | ||
``` | ||
$ npm install grex | ||
``` | ||
then in node | ||
then in Node or the browser | ||
@@ -51,2 +50,26 @@ ``` | ||
## Connnecting to a database | ||
``` | ||
//connect takes options object and returns a Promise | ||
g.connect({ 'database': 'myGraphDB', | ||
'host': 'my.host.com', | ||
'port': 8000 }).then(function(graphDB){ | ||
//once connected the return value is a reference to the graph | ||
trxn = graphDB.begin(); | ||
t1 = trxn.addVertex({name:'Test1a'}); | ||
t2 = trxn.addVertex({name:'Test2a'}); | ||
trxn.addEdge(t1, t2, 'linked', {name:"ALabel"}) | ||
trxn.commit().then(function(result){ | ||
console.log("Added new vertices successfully. -> ", result); | ||
}, function(err) { | ||
console.error(err) | ||
}); | ||
}); | ||
``` | ||
## Introduction | ||
@@ -57,5 +80,5 @@ | ||
* All method calls require brackets __()__, even if there are no arguments. | ||
* __Closures__ do not translate to javascript. Closures need to passed in as one string argument to gRex methods. | ||
* __Closures__ do not translate to javascript. Closures need to passed in as a string argument to gRex methods. | ||
```e.g. | ||
``` | ||
g.v(1).out().gather("{it.size()}"); | ||
@@ -67,9 +90,11 @@ | ||
```e.g. | ||
``` | ||
g.v(1).outE().has("weight", "T.gte", "0.5f").property("weight") | ||
``` | ||
* Certain methods cannot be implemented. Such as ``aggregate``, ``store``, ``table``, ``tree`` and ``fill``. These methods take a local object and populate it with data, which cannot be done in this environment. | ||
* Certain methods cannot be implemented. Such as ``aggregate``, ``store``, ``table``, ``tree`` and ``fill``. These methods require a local object to populate with data, which cannot be done in this environment. | ||
## Getting Started | ||
A good resource to understand the Gremlin API is [GremlinDocs](http://gremlindocs.com/). Below are examples of gremlin and it's equivalent gRex syntax. | ||
###Options | ||
@@ -95,14 +120,10 @@ | ||
```e.g. | ||
``` | ||
g.setOptions({ host: 'myDomain', graph: 'myOrientdb', idRegex: /^[0-9]+:[0-9]+$/ }); | ||
``` | ||
## Examples | ||
__N.B.:__ gRex uses the [Q](http://documentup.com/kriskowal/q/) module to return a Promise when making Ajax calls. All requests are invoked with ``then()`` and the callback is captured by ``then(result, error);``. However, this is not the case when performing Create, Update and Deletes of Vertices or Edges. These actions are batched to reduce the number of calls to the server. In order to send these type of requests a Transaction must be created by calling ``var trxn = g.begin();``. Updates are made against this object. Once all updates are done, invoke ``trxn.commit().then(result, error);`` to commit your changes. See examples below. | ||
A good resource to understand the Gremlin API is [GremlinDocs](http://gremlindocs.com/). Below are examples of gremlin and it's equivalent gRex syntax. | ||
__N.B.:__ gRex uses the [Q](http://documentup.com/kriskowal/q/) module to return a Promise when making Ajax calls. All requests are invoked with ``then()`` and the callback is captured by ``then(result, error);``. However, this is not the case when performing Create, Update and Deletes of Vertices or Edges. These actions are batched to reduce the number of calls to the server. In order to send these type of requests invoke ``g.commit().then(result, error);`` after making your updates to the data. See examples below. | ||
__Calls invoked with then()__ | ||
```javascript | ||
``` | ||
g.V('name', 'marko').out().then(function(result){console.log(result)}, function(err){console.log(err)}); | ||
@@ -113,20 +134,103 @@ | ||
__Creating, updating or deleting Vetices or Edges. Use g.commit() to commit all changes.__ | ||
__Creating, updating or deleting Vetices or Edges. Use commit() to commit changes.__ | ||
``` | ||
gRex> g.addVertex(100, {k1:'v1', 'k2':'v2', k3:'v3'}); | ||
gRex> var trxn = g.begin(); | ||
gRex> g.addVertex(200, {k1:'v1', 'k2':'v2', k3:'v3'}); | ||
gRex> trxn.addVertex(100, {k1:'v1', 'k2':'v2', k3:'v3'}); | ||
gRex> g.addEdge(300,100,200,'pal',{weight:'0.75f'}) | ||
gRex> trxn.addVertex(200, {k1:'v1', 'k2':'v2', k3:'v3'}); | ||
gRex> g.updateVertex(100, {k2: 'v4'}); | ||
gRex> trxn.addEdge(300,100,200,'pal',{weight:'0.75f'}) | ||
gRex> g.removeVertex(100, ['k2', 'k3']); | ||
gRex> trxn.updateVertex(100, {k2: 'v4'}); | ||
gRex> g.removeVertex(200); | ||
gRex> trxn.removeVertex(100, ['k2', 'k3']); | ||
gRex> g.commit().then(function(result){console.log(result)}, function(err){console.log(err)}); | ||
gRex> trxn.removeVertex(200); | ||
gRex> trxn.commit().then(function(result){console.log(result)}, function(err){console.log(err)}); | ||
``` | ||
## Property Data Types | ||
[Rexster Graph Server](https://github.com/tinkerpop/rexster/wiki) supports the following Property Data Types: | ||
- Strings | ||
- Boolean | ||
- Integer | ||
- Long | ||
- Float | ||
- Double | ||
- List (Array) | ||
- Map | ||
gRex automatically preserves data types. It uses type values obtained from the server, when data is retrieved, to ascertain data types. If a property's data type is unknown, gRex will not try to infer the data type and will simply allow the value to be passed as a string, which is the default behaviour. However, it is possible to provide a type definition to a Transaction, which will then be used to pass type information to the server during a POST. | ||
### Type Definition | ||
When Rexster returns data, it will include Type information, gRex will create a Type definition based on this information to be used in subsequent POST requests. Type definitions can only be generated for Objects that have been retrieved from the server. So, if you are updating or creating a 'Person' object the type definition will only be available if a 'Person' object was previously requested and retrieved from teh server. | ||
Also, if totally new properties need to have a Type definition, so that gRex can understand how to send the information to the server. | ||
A Type definition is an Object and is used globally. For example, if 'age' has been defined as type integer in a 'Person' object, then whenever gRex encounters an 'age' property, regardless of the Object, it will be treated as an integer. Although, if the 'age' property is embedded in another object, then it will need to be explicitly defined. | ||
You are only required to provide a Type definition for properties that are being added. | ||
### Creating a Type Definition | ||
In order to use a Type Definition, you pass in an Object to the Transaction ``begin`` function. | ||
#### Simple Type Definition | ||
A Type definition is an Object Literal. The key is the property name for the Object you are providing a Type definition for and the value is the Type that is being assigned to that property. For example, to define a property as boolean for a key called 'active' you would do the following: | ||
```{ active: 'boolean' }``` | ||
OR | ||
```{ active: 'b' }``` | ||
This is the similar for all the simple Types. | ||
- Strings = 'string' or 's' | ||
- Boolean = 'boolean' or 'b' | ||
- Integer = 'integer' or 'i' | ||
- Long = 'long' or 'l' | ||
- Float = 'float' or 'f' | ||
- Double = 'double' or 'd' | ||
Complex types, such as ``list`` and ``map`` are a little different. | ||
#### List Type Definition | ||
To define a Type for are List (Array), you simply provide an Array as the value and provide the type name for each item in the array. You will need to know which index a particular Type will be located. Any items added to the array after item[3] will be added as the last Type defined in the array, in this instance the items will be added as integers. | ||
```{ items: ['string', 'string', 'boolean', 'integer'] }``` | ||
#### Map Type Definition | ||
Map Type's are simply object literals. To define a map type you pass in objects much the same as defining a simple type above. | ||
```{ address: { number: 'integer', street: 'string', city: 'string'} }``` | ||
Both List and Map Types can have embedded list and map types. | ||
* list with embedded map [NB. There is currently a bug for maps embedded in lists] | ||
```{ items: ['string', {age: 'integer'}, 'boolean', 'integer'] }``` | ||
* map with embedded list | ||
```{ address: { number: 'integer', street: 'string', city: 'string', occupantNames:['string']} }``` | ||
#### Type Definition Usage | ||
To use a Type definition, just pass it to the ``begin`` function of a transaction. | ||
``` | ||
var typeDef = { active: 'boolean', | ||
items: ['string', 'string', 'boolean', 'integer'], | ||
address: { number: 'integer', street: 'string', city: 'string', occupantNames:['string']} | ||
}; | ||
var trxn = new g.begin(typeDef); | ||
``` | ||
If there is already a Type definition for a property, the passed in type definition is merged with the existing type definition and takes precedence. | ||
## Examples | ||
For simplicity the callbacks are not included in the examples below. | ||
@@ -239,15 +343,17 @@ | ||
``` | ||
gRex> g.addVertex(100, {k1:'v1', 'k2':'v2', k3:'v3'}); | ||
gRex> var trxn = g.begin(); | ||
gRex> g.addVertex(200, {k1:'v1', 'k2':'v2', k3:'v3'}); | ||
gRex> trxn.addVertex(100, {k1:'v1', 'k2':'v2', k3:'v3'}); | ||
gRex> g.addEdge(300,100,200,'pal',{weight:'0.75f'}) | ||
gRex> trxn.addVertex(200, {k1:'v1', 'k2':'v2', k3:'v3'}); | ||
gRex> g.updateVertex(100, {k2: 'v4'}); | ||
gRex> trxn.addEdge(300,100,200,'pal',{weight:'0.75f'}) | ||
gRex> g.removeVertex(100, ['k2', 'k3']); | ||
gRex> trxn.updateVertex(100, {k2: 'v4'}); | ||
gRex> g.removeVertex(200); | ||
gRex> trxn.removeVertex(100, ['k2', 'k3']); | ||
gRex> g.commit() | ||
gRex> trxn.removeVertex(200); | ||
gRex> trxn.commit() | ||
``` | ||
@@ -258,20 +364,15 @@ | ||
``` | ||
var trxn = g.begin(); | ||
var v1, v2; | ||
v1 = g.addVertex({name:'Frank'}); | ||
v2 = g.addVertex({name:'Luca'}); | ||
g.addEdge(v1, v2, 'knows', {since:"2003/06/01"}) | ||
v1 = trxn.addVertex({name:'Frank'}); | ||
v2 = trxn.addVertex({name:'Luca'}); | ||
trxn.addEdge(v1, v2, 'knows', {since:"2003/06/01"}) | ||
v1 = g.addVertex({name:'Stephen'}); | ||
v2 = g.addVertex({name:'James'}); | ||
g.addEdge(v2, v1, 'knows', {since:"2000/01/01"}) | ||
v1 = trxn.addVertex({name:'Stephen'}); | ||
v2 = trxn.addVertex({name:'James'}); | ||
trxn.addEdge(v2, v1, 'knows', {since:"2000/01/01"}) | ||
g.commit().then(function(result){ | ||
if (result) { | ||
if (result.success == false) { | ||
console.error("Failed to add vertices."); | ||
} else { | ||
console.log("New vertices -> ", result); | ||
} | ||
} | ||
trxn.commit().then(function(result){ | ||
console.log("New vertices -> ", result); | ||
}, function(err) { | ||
@@ -281,5 +382,4 @@ console.error(err) | ||
This will return a JSON object with an array called newVertices. | ||
eg. | ||
//This will return a JSON object with an array called newVertices. For example: | ||
{ success: true, | ||
@@ -294,2 +394,28 @@ newVertices: | ||
__Example 14: Create index__ | ||
``` | ||
var y = "bob"; | ||
var trxn = g.begin(); | ||
var vertex = trxn.addVertex({name:y}); | ||
trxn.commit().then | ||
(function(result) { | ||
console.log("Added a vertex successfully for", y); | ||
g.createIndex('actor', 'Vertex.class').then | ||
(function(result){ | ||
g.idx('actor').put('name', y, g.v(vertex._id)).then | ||
(function(result){ | ||
console.log("Index added successfully for", y); | ||
}, function(err) { | ||
console.log(err) | ||
}); | ||
}, function(err) { | ||
console.log(err) | ||
}); | ||
}, function(err) { | ||
console.log(err) | ||
}); | ||
``` | ||
## Author | ||
@@ -296,0 +422,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
216935
15
1715
423
7
2
5
4