Session API

A Session instance can be used for:

  • Run a Query (Idempotent SQL statement)
  • Run a Command (Idempotent or non idempotent SQL statement)
  • Run a Batch Script
  • Execute a Transaction
  • Execute a live query
  • Use query builder

To obtain a Session instance use the Client APIs.

By convention, the variable on which you initialize the Session API is called session. This designation is arbitrary and used only for convenience.

Query

The session.query method executes an idempotent SQL query against the opened database. You can either define these values directly in SQL, or define arbitrary parameters through additional arguments. The API call returns an extension of Node.js Streams.

Streaming

session.query("select from OUser where name = :name", {params: { name: "admin" }})
	.on("data", data => {
		console.log(data);
	})
	.on('error',(err)=> {
	  console.log(err);
	})
	.on("end", () => {
		console.log("End of the stream");
	});

To Promise

Use .all API that convert the stream to a Promise and collect the result set into an array

session.query("select from OUser where name = :name", { params : {name: "admin" }})
.all()
.then((results)=> {
	console.log(results);
});

or with async/await

try {
	let results = await session
	.query("select from OUser where name = :name", {
		params: { name: "admin" }
	})
	.all();
	console.log(results);
} catch (e) {
	console.log(e);
}

Alternatively use .one API for the first entry only

session.query("select from OUser where name = :name", { params : {name: "admin" }})
.one()
.then((results)=> {
	console.log(results);
});

or with async/await

try {
	let results = await session
	.query("select from OUser where name = :name", {
		params: { name: "admin" }
	})
	.one();
	console.log(results);
} catch (e) {
	console.log(e);
}

Command

The session.command method executes a SQL query against the opened database and accept non idempotent queries like insert into, create vertex etc. The API call returns an extension of Node.js Streams.

session.command("insert into V set name = :name", {params: { name: "test" }})
.all()
.then(result => {
	console.log(result);
});

or with async/await

try {
	let results = await session
	.command("insert into V set name = :name", { params: { name: "test" } })
	.all();
	console.log(results);
} catch (e) {
	console.log(e);
}

Batch Script

The batch method executes a Multiple SQL query against the opened database. The API call returns an extension of Node.js Streams.

let batch = `begin;
	let $v1 = create vertex V set name = "first";
	let $v2 = create vertex V set name = "second";
	let $e = create edge E from $v1 to $v2;
	commit;
	return  $e;`;
	
session.batch(batch).all()
  .then(results => {
    console.log(results);
  });

or with async/await

try {
	let batch = `begin;
	let $v1 = create vertex V set name = "first";
	let $v2 = create vertex V set name = "second";
	let $e = create edge E from $v1 to $v2;
	commit;
	return  $e;`;

	let results = await session.batch(batch).all();
	console.log(results);
} catch (e) {
	console.log(e);
}

Query/Command/Script Options

Those APIs accepts an options object as second parameter.

The options can contains:

  • Query parameters
  • Additional Configuration

Using Parameters

The options object can contain a params property that represent the query parameters to use.

Named parameters

session.command("insert into V set name = :name", {params: { name: "test" }})
.all()
.then(result => {
	console.log(result);
});

Positional parameters

session.command("insert into V set name = ?", {params: ["admin"]})
.all()
.then(result => {
	console.log(result);
});

Additional configuration

Starting from OrientDB 3.0, the result set from a query/command/script is paginated. By default OrientJS uses a page size of 100 records. Use the additional property pageSize to tune this configuration.

session.command("select name from V", {
	params: ["admin"],
	pageSize: 1000
})
.all()
.then(results => {
	console.log(results);
});

Transactions

Use the api session.runInTransaction in order to run a unit of work in a managed transaction (begin/commit/retry). The unit of work provided in input should return a Promise. The return of session.runInTransaction is a Promise that once resolved, returns the result of the last operation in the unit of work and the result of the commit of the transaction.

The Session supports only 1 transaction at time. Use multiple sessions if you want to run concurrent transactions.

session.runInTransaction((tx)=>{
	return tx.command("insert into V set name = :name", {params: { name: "test" }})
	.all();
}).then(({result,tx}) => {
	console.log(result);
	console.log(tx);
});

alternatively using explicit API

session.begin();
session.command("insert into V set name = :name", {
	params: { name: "admin" }})
	.one()
	.then(results => {
		console.log(results);
		return session.commit();
	})
	.then(results => {
		console.log(results);
	});

Live Queries

When using traditional queries, such as those called with session.query() and session.select() you only get data that is current at the time the query is issued. Beginning in version 2.1, OrientDB now supports Live Queries, where in issuing the query you tell OrientDB you want it to push affecting changes to your application.

You can execute Live Queries using the session.liveQuery() method with a LIVE SELECT statement passed as its argument.

Understanding Live Queries

Traditional queries provide you with information that is current at the time the query is issued. In most cases, such as well pulling statistical data on long-dead ball players like Ty Cobb, this behavior is sufficient to your needs. But, what if about when you need real time information.

For instance, what if in addition to historical data you also want your application to serve real-time information about baseball games as they're being played.

With the traditional query, you would have to reissue the query within a set interval to update the application. Live Queries allow you to register events, so that your application performs addition operations in the event of an INSERT, DELETE, or UPDATE.

For example, say that you have a web application that uses the baseball database. The application serves the current score and various other stats for the game. Whenever your back-end system inserts new records for the game, you can execute a function to update the display information.

Working with Live Queries

In OrientJS, Live Queries are called using the session.liveQuery() method. This is similar to session.query() in that you use it to issue the raw SQL of a LIVE SELECT statement. You can assign event handlers to session.liveQuery using the on('data') method. The methods returns an extension of Node.JS Streams

For instance,

session.liveQuery("select from V").on("data", data => {
	console.log(data);
});

The data object is emitted every time the live query is matched and it contains those properties

  • monitorId : identifier of the live query on the server.
  • operation : identifier of the operation executed
    • 1 - Create
    • 2 - Update
    • 3 - Delete
  • data : the actual matched record.
  • before : in case of update, the previously version of the record changed.
{ 
	monitorId: 275616756,
	operation: 1,
	data:
  		{ 
  			name: 'Foo',
     		'@rid': RecordID { cluster: 10, position: 12 },
     		'@class': 'V',
     		'@version': 1 
     	} 
}

Unsubscribing Live Queries

To unsubscribe a live query, use the API handle.unsubscribe where handle is the returned value of the liveQuery function

let handle = session.liveQuery("select from V").on("data", data => {
	console.log(data);
	handle.unsubscribe();
});

Query Builder

Rather than writing out query strings in SQL, you can alternatively use the OrientJS Query Builder to construct queries using a series of methods connected through the Database API.

  • create: Creates vertices and edges.
  • insert: Insert records
  • update: Modifies records on database.
  • delete: Removes vertices, edges, and records.
  • select: Fetches records by query.

Create

Creation queries in OrientJS are those used in creating vertex and edge records on a Graph Database. Given the added complexity of regular or lightweight edges running between the vertices, adding records is a little more complicated than the insert() method you might use otherwise.

The creation query method is comparable to the CREATE VERTEX and CREATE EDGE commands on the OrientDB Console.

In OrientJS, creating vertices and edges uses the create() method. The examples below operate on a database of baseball statistics, which has been initialized on the db variable.

Creating Vertices

Create an empty vertex on the Player vertex class:

session.create("VERTEX", `Player`).one()
	.then(results => {
		console.log(results);
	});

Create a vertex with properties:

session.create("VERTEX", "Player")
	.set({
		name: "Ty Cobb",
		birthDate: "1886-12-18",
		deathDate: "1961-7-17",
		batted: "left",
		threw: "right"
	})
	.one()
	.then((player)=> {
		console.log(player);
	});

Creating Edges

Creating edges to connect two vertices follows the same pattern as creating vertices, with the addition of from() and to() methods to show the edge direction.

For instance, consider an edge class PlaysFor that you use to connect player and team vertices. Using it, you might create a simple edge that simply establishes the connection:

session.create("EDGE", "PlaysFor")
	.from("#12:12").to("#12:13")
	.one()
	.then(edge => {
		console.log(edge);
	});

This creates an edge between the player Ty Cobb, (#12:12), and the Detroit Tigers, (#12:13). While this approach may be useful with players that stay with the same team, many don't. In order to account for this, you would need to define properties on the edge.

session.create("EDGE", "PlaysFor")
	.from("#12:12").to("#12:13")
	.set({
		startYear: "1905",
		endYear: "1926"
	})
	.one()
	.then(edge => {
		console.log(edge);
	});

Now, whenever you build queries to show the players for a team, you can include conditionals to only show what teams they played for in a given year.

Insert

Insertion queries in OrientJS are those that add records of a given class into the database. The insertion query method is comparable to the INSERT commands on the OrientDB Console.

Example

In OrientJS, inserting data into the database uses the insert() method. For instance, say that you want to add batting averages, runs and runs batted in for Ty Cobb.

session.insert().into("Player")
	.set({
		ba: 0.367,
		r: 2246,
		rbi: 1938
	})
	.one()
	.then((player) => {
		console.log(player);
	});
Raw Expressions
session.insert().into('Player')
	.set({
		uuid : session.rawExpression("format('%s',uuid())"),
	  	ba:  0.367,
	  	r:   2246,
	  	rbi: 1938
	}).one().then((player)=>{
	   console.log(player)
	});

Generated Query

INSERT INTO Player SET uuid = format('%s',uuid()), ba = 0.367, r = 2246, rbi = 1938

Update

Update queries in OrientJS are those used in changing or otherwise modifying existing records in the database. The method is comparable to the UPDATE command on the OrientDB Console.

In OrientJS, updating records works through the update() method. The examples below operate on a database of baseball statistics, which has been initialized on the session variable.

Updating Records

When the record already exists in the database, you can update the content to modify the current values stored on the class.

Consider the case where you want to update player data after a game. For instance, last night the Boston Red Sox played and you want to update the batting average for the player Tito Ortiz, who has a Record ID #12:97.

session.update("#12:97")
	.set({
		ba: 3.1
	})
	.one()
	.then(update => {
		console.log("Records Updated:", update);
	});

If you don't know the RecordID, alternatively and more likely you can update with a where condition, for example on the name of the player.

session.update("Player")
	.set({
		ba: 3.1
	})
	.where({ name: "Ty Cobb" })
	.one()
	.then(update => {
		console.log("Records Updated:", update);
	});

Delete

Deletion queries in OrientJS are those used in removing records from the database. It can also account for edges between vertices, updating the graph to maintain its consistency.

The deletion query method is comparable to DELETE, DELETE VERTEX and the DELETE EDGE statements.

In OrientJS, deletions use the delete() method. The examples below operate on a database of baseball statistics, which has been initialized on the session variable.

Deleting Vertices

With Graph Databases, deleting vertices is a little more complicated than the normal process of deleting records. You need to tell OrientDB that you want to delete a vertex to ensure that it takes the additional steps necessary to update the connecting edges.

For instance you want to remove the player Ty Cobb.

session.delete("VERTEX", "Player")
	.where({ name: "Ty Cobb" })
	.one()
	.then((del)=> {
		console.log("Records Deleted: " + del);
	});

Deleting Edges

When deleting edges, you need to define the vertices that the edge connects. For instance, consider the case where you have a bad entry on the playsFor edge, where you have Ty Cobb assigned to the Chicago Cubs. Ty Cobb has a Record ID of #12:12, the Chicago Cubs #12:54.

session.delete('EDGE', 'PlaysFor')
	.from('#12:12').to('#12:54')
	.one()
	.then((del)=>{
	     console.log('Records Deleted: ' + del);
	  }
	);

Deleting Records

In order to delete records in a given class, you need to define a conditional value that tells OrientDB the specific records in the class that you want to delete. When working from the Console, you would use the WHERE clause. In OrientJS, set the where() method.

session.delete().from('Player')
	.where('@rid = #12:84').limit(1).scalar()
	.then((del)=>{
	     console.log('Records Deleted: ' + del);
	  }
	);

Select

Selection queries in OrientJS are those used to fetch data from the database, so that you can operate on it with your application. The method is comparable to the SELECT command in the OrientDB Console.

In OrientJS, fetching data from the database uses the select() method. The examples below operate on a database of baseball statistics, which has been initialized on the db variable.

Selecting Records

Use the select() method to fetch records from the database. For instance, say you want a lit of all players with a batting average of .300.

session.select().from("Player")
	.where({
		ba: 0.3
	})
	.all()
	.then(function(select) {
		console.log("Hitters:", select);
	});

Custom Where

The where clause can take a JSON object for expressing condition. For more complex condition the where clause can take a string with custom conditions and pass eventual parameters in one of the selected query terminator (one/all/stream/scalar)

session.select().from("Player")
	.where("ba >= :ba")
	.all({ ba : 0.3})
	.then((select) => {
		console.log("Hitters:", select);
	});

Using Expressions

In the event that you would like to return only certain properties on the class or use OrientDB functions, you can pass the expression as an argument to the select() method.

For instance, say you want to know how many players threw right and batted left:

session.select("count(*)").from("Player")
	.where({
		threw: "right",
		batted: "left"
	})
	.scalar()
	.then((select) => {
		console.log("Total:", select);
	});

Returning Specific Fields

Similar to expressions, by passing arguments to the method you can define a specific field that you want to return. For instance, say you want to list the teams in your baseball database, such as in building links on a directory page.

session.select("name").from("Teams")
	.all()
	.then((select)=> {
		console.log("Loading Teams:", select);
	});

Specifying Default Values

Occasionally, you may encounter issues where your queries return empty fields. In the event that this creates issues for how your application renders data, you can define default values for certain fields as OrientJS sets them on the variable.

For instance, in the example of the baseball database, consider a case where for some historical players the data is either currently incomplete or entirely unavailable. Rather than serving null values, you can set default values using the defaults() method.

session.select("name").from("Player")
	.defaults({
		throws: "Unknown",
		bats: "Unknown"
	}).all()
	.then(players => {
		console.log(players);
	});