Shell
From Neo4j Wiki
If you're just looking for an example try the Shell Matrix Example, otherwise read on. This is like a manual for the Shell.
Neo4j shell is a command-line shell for browsing the graph, much like how the Unix shell along with commands like cd, ls and pwd can be used to browse your local filesystem. It consists of two parts: a lightweight client that sends commands via RMI and a server that processes those commands and sends the result back to the client. It's a nice tool for development and debugging. This guide will show you how to get it going!
Contents |
[edit] The remote shell server
There are two parts to installing and enabling the remote shell server. First, you need to make sure that the shell jar file is on the classpath when you start up your Neo4j instance.
[edit] Include the shell jar
- If you don't use maven, go to http://neo4j.org/download and download the latest release of the
neo4j-shell-SOME_VERSION.jarfile. Then add it to your-classpathcommand line switch, or to your ant-enabledlibfolder, or right-click and add-to-build-path in Eclipse or however you add jar files to your classpath in your environment. - If you use maven (and have added the Neo4j m2 repository to the
<repositories>-tag in your pom as outlined in the Getting Started Guide): add the following to yourpom.xml:
<dependency> <groupId>org.neo4j</groupId> <artifactId>neo4j-shell</artifactId> <version>SOME_VERSION</version> <!-- latest current version, as of 2010-02-16, is 1.0 --> </dependency>
[edit] Enabling the remote shell server
Now that you have got the shell jar file you have two options.
- You can start up a JVM with a GraphDabaseService instance and programmatically enable the remote shell server. You do this by invoking the
enableRemoteShell()method in theGraphDatabaseServiceclass as follows:
GraphDatabaseService graphDb = new EmbeddedGraphDatabase( "graphdb" ); graphDb.enableRemoteShell();
There's also an enableRemoteShell() method that takes a map with configuration info, see Neo4j kernel javadocs for more information.
[edit] Starting the shell
There are two ways to start the shell, either by connecting to a remote shell server or by pointing it to a Neo4j store path.
[edit] Connecting to a remote shell server
To start the shell and connect to a running remote shell server, run:
java -jar neo4j-shell-<version>.jar
Alternatively supplying -port and -name options if depending on how the remote shell server was enabled. Then you'll get the shell prompt like this:
neo4j-sh (0)$
[edit] Pointing the shell to a path
To start the shell by just pointing it to a Neo4j store path you run the shell jar file. Given that the right neo4j-kernel-<version>.jar and jta jar files are in the same path as your neo4j-shell-<version>.jar file you run it with:
$ java -jar neo4j-shell-<version>.jar -path path/to/neo4j-db
Else you can try the packaged shell distribution,
/../neo4j-shell-[version]-standalone/bin/neo4j-shell -path [path/to/db]
or include those jar files manually, f.ex. with:
$ java -cp neo4j-shell-<version>.jar:neo4j-kernel-<version>.jar:geronimo-a_1.1_spec-1.1.1.jar
org.neo4j.shell.StartClient -path path/to/graphdb
[edit] Notes about passing options and arguments
Passing options and arguments to your commands is very similar to many CLI commands in an *nix environment. Options are prefixed with a - and can contain one or more options. Some options expect a value to be associated with it. Arguments are string values which aren't prefixed with -. Let's look at ls as an example:
ls -r -d OUTGOING -v 12345 will make a verbose listing of node 12345's relationships which have the direction OUTGOING. The node id, 12345, is an argument to ls which tells it to do the listing on that node instead of the current node (see pwd command). However a shorter version of this can be written:
ls -rdv OUTGOING 12345. Here all three options are written together after a single '-' prefix. Even though the d is in the middle it gets associated with the OUTGOING value. The reason for this is that the ls command doesn't expect any values associated with the r or v options, hence it can infer that the OUTGOING value refers the d option.
[edit] Notes about enum options
Some options expects a value which is one of the values in an enum, f.ex. direction (-d in ls) where there's INCOMING, OUTGOING and BOTH. All such values can be supplied in an easier way. It's enough that you write the start of the value and the interpreter will find what you really meant. So if we look at ls again you can supply the -d option value like: out, in, i or even INCOMING.
[edit] Notes about filters
Some commands makes use of filters for varying purposes. F.ex. -f in ls and in trav. A filter is supplied as a json object (w/ or w/o the surrounding {} brackets and where both keys and values can contain regular expressions for a more flexible matching. An example of a filter could be .*url.*:http.*neo4j.*,name:Neo4j. The filter option is also accompanied by the options -i and -l which stands for ignore case (ignore casing of the characters) and loose matching (it's considered a match even if the filter value just matches a part of the compared value, not necessarily the entire value). So for a case-insensitive, loose filter you can supply a filter with -f -i -l or -fil for short.
[edit] Notes about node titles
To make it easier to navigate your graph the shell can display a title for each node, f.ex. in a ls -r command. It will display the relationships as well as the nodes on the other side of the relationships. The title is displayed together with each node and its best suited property value from a list of property keys.
F.ex. if you're standing on a node which has two KNOWS relationships to other nodes it'd be difficult to know which friend is which. The title feature addresses this by reading a list of property keys and grabbing the first existing property value of those keys and displays it as a title for the node. So you may specify a list (with or without regular expressions), f.ex: name,title.*,caption and the title for each node will be the property value of the first existing key in that list. The list is defined by the client (you) using the TITLE_KEYS environment variable and the default being .*name.*,.*title.*
[edit] How to use (individual commands)
The shell is modelled after Unix shells like bash that you use to walk around your local file system. It has some of the same commands, like cd and ls. When you first start the shell (see instructions above), you will get a list of all the available commands. Use man <command> to get more info about a particular command. Some notes:
[edit] Current node/relationship and path
You have a current node/relationship and a "current path" (like a current working directory in bash) that you've traversed so far. You start at the reference node and can then cd your way through the graph (check your current path at any time with the pwd command). cd can be used in different ways:
-
cd <node-id>will traverse one relationship to the supplied node id. The node must have a direct relationship to the current node. -
cd -a <node-id>will do an absolute path change, which means the supplied node doesn't have to have a direct relationship to the current node. -
cd -r <relationship-id>will traverse to a relationship instead of a node. The relationship must have the current node as either start or end point. To see the relationship ids use thels -vrcommand. -
cd -ar <relationship-id>will do an absolute path change which means the relationship can be any relationship in the graph. -
cdwill take you back to the reference node, where you started in the first place. -
cd ..will traverse back one step to the previous location, removing the last path item from your current path (pwd). -
cd start(only if your current location is a relationship). Traverses to the start node of the relationship. -
cd end(only if your current location is a relationship). Traverses to the end node of the relationship.
[edit] Listing contents of a node/relationship
List contents of the current node/relationship (or any other node) with the ls command. Please note that it will give an empty output if the current node/relationship has no properties or relationships (for example in the case of a brand new graph). ls can take a node id as argument as well as filters, see #Notes about filters and for information about how to specify direction see #Notes about enum options. See man ls for more info.
[edit] Creating nodes and relationships
You create new nodes by connecting them with relationships to the current node. For example, mkrel -t A_RELATIONSHIP_TYPE -d OUTGOING -c will create a new node (-c) and draw to it an OUTGOING relationship of type A_RELATIONSHIP_TYPE from the current node. If you already have two nodes which you'd like to draw a relationship between (without creating a new node) you can do for example, mkrel -t A_RELATIONSHIP_TYPE -d OUTGOING -n <other-node-id> and it will just draw a new relationship between the current node and that other node.
[edit] Setting, renaming and removing properties
Property operations are done with the set, mv and rm commands. These commands operates on the current node/relationship.
-
set <key> <value>with optionally the-toption (for value type) sets a property. Supports every type of value that Neo4j supports. Examples of a property of typeint:
$ set -t int age 29
And an example of setting a double[] property:
$ set -t double[] my_values [1.4,12.2,13]
-
rm <key>removes a property. -
mv <key> <new-key>renames a property from one key to another.
[edit] Deleting nodes and relationships
Deleting nodes and relationships is done with the rmrel command. It focuses on deletion of relationships, but a node can also be deleted if the deleted relationship leaves the opposite node "stranded" (i.e. it no longer has any relationships drawn to it) and the -d options is supplied. See the relationship ids with the ls -rv command.
[edit] Environment variables
The shell uses environment variables a-la bash to keep session information, such as the current path and more. The commands for this mimics the bash commands export and env. For example you can at anytime issue a export STACKTRACES=true command to set the STACKTRACES environment variable to true. This will then result in stacktraces being printed if an exception or error should occur. List environment variables using env
[edit] Executing groovy/python scripts
The shell has support for executing scripts, such as Groovy and Python (via Jython). As of now the scripts (*.groovy, *.py) must exist on the server side and gets called from a client with for example, gsh --renamePerson 1234 "Mathias" "Mattias" --doSomethingElse where the scripts renamePerson.groovy and doSomethingElse.groovy must exist on the server side in any of the paths given by the GSH_PATH environment variable (defaults to .:src:src/script). This variable is like the java classpath, separated by a :. The python/jython scripts can be executed with the jsh in a similar fashion, however the scripts have the .py extension and the environment variable for the paths is JSH_PATH.
When writing the scripts assume that there's made available an args variable (a String[]) which contains the supplied arguments. In the case of the renamePerson example above the array would contain ["1234", "Mathias", "Mattias"]. Also please write your outputs to the out variable, such as out.println( "My tracing text" ) so that it will be printed at the shell client instead of the server.
[edit] Traverse
You can traverse the graph with the trav command which allows for simple traversing from the current node. You can supply which relationship types (w/ regex matching) and optionally direction as well as property filters for matching nodes. In addition to that you can supply a command line to execute for each match. An example: trav -o depth -r KNOWS:both,HAS_.*:incoming -c "ls $n". Which means traverse depth first for relationships with type KNOWS disregarding direction and incoming relationships with type matching HAS_.* and do a ls <matching node> for each match. The node filtering is supplied with the -f option, see #Notes about filters. See #Notes about enum options for the traversal order option. Even relationship types/directions are supplied using the same format as filters.
[edit] Indexing
It's possible to reach and manipulate indexes (i.e. instances of IndexService) via the index command. You control which index service to use with the INDEX_CLASS_NAME environment variable (defaults to org.neo4j.index.lucene.LuceneIndexService if none is given). Options to the index command are:
-
-gwhich will query the index and display hits. You can supply-cwith a command to be executed for each hit. -
--cdwhich will imply the-goption and will change current location to the hit from the query. It's just a convenience for using the-coption. -
--lswhich will imply the-goption and will do a listing of the contents for each hit. It's just a convenience for using the-coption. -
-iwhich will index a key-value pair for the current node. If no value is given the property value for that key for the current node is used as value. -
-rwhich will remove a key-value pair (if it exists) from the index for the current node. If no value is given the property value for that key for the current node is used as value.
[edit] Extending the shell: Adding your own apps
Of course the shell is extendable and has a generic core which has nothing to do with Neo4j... only some of the apps do.
So you say you'd like to start a Neo4j graph database, enable the remote shell and add your own apps to it so that your apps and the standard Neo4j apps co-exist side by side? Well, here's an example of how an app could look like:
public class LsRelTypes extends GraphDatabaseApp
{
@Override
protected String exec( AppCommandParser parser, Session session, Output out )
throws ShellException, RemoteException
{
GraphDatabaseService graphDb = getServer().getDb();
out.println( "Types:" );
for ( RelationshipType type : graphDb.getRelationshipTypes() )
{
out.println( type.name() );
}
return null;
}
}
To start up a shell with some additional apps in it you can do like this:
GraphDatabaseService graphDb = new EmbeddedGraphDatabase( "my/path" );
// IMPORTANT: Don't enable the remote shell in the normal way
// graphDb.enableRemoteShell();
// Instead instantiate your own and add apps to it
GraphDatabaseShellServer shellServer = new GraphDatabaseShellServer( graphDb );
shellServer.addApp( LsRelTypes.class );
shellServer.makeRemotelyAvailable( AbstractServer.DEFAULT_PORT,
AbstractServer.DEFAULT_NAME );
And you could now use it in the shell by typing lsreltypes (its name is based on the class name).
If you'd like it to display some nice help information when using the help (or man) app, override the getDescription method for a general description and use addValueType method to add descriptions about (and logic to) the options you can supply when using your app.
Know that the apps reside server-side so if you have a running server and starts a remote client to it from another JVM you can't add your apps on the client.

