Skip to content

Indexes

jadell edited this page Nov 27, 2012 · 9 revisions

In a graph database, an index is used as a way to quickly look up nodes and relationships. Entities can be indexed on any key/value pair. The key and value do not have to be properties on the entity.

Managing Indexes

It's important to note that indexes do not need to be created before they are used. The first time an entity is added to an index that does not exist, the index will be created on the server with a default configuration (except for full-text indexes, which must be saved before they are used.)

Index Types

There are 3 provided index classes:

  1. Everyman\Neo4j\Index\NodeIndex
  2. Everyman\Neo4j\Index\RelationshipIndex
  3. Everyman\Neo4j\Index\NodeFulltextIndex

It is also possible to define custom indexes by instantiating or extending the base Everyman\Neo4j\Index class with custom configuration.

Create and Remove an Index

Indexes can be created independently of adding entities. The following code creates an index and then saves the index to the server.

$shipIndex = new Everyman\Neo4j\Index\NodeIndex($client, 'ships');
$shipIndex->save();

The Index::save() operation will return true if the index was successfully saved, and throw an exception otherwise.

An index can be removed from the server, which will also remove any key/values that have been added to that index.

// Delete the ship index from the above example
$shipIndex->delete();

// Delete an index that had been created previously
$planetIndex = new Everyman\Neo4j\Index\NodeIndex($client, 'planets');
$planetIndex->delete();

The Index::delete() operation will return true if the index was successfully deleted, and throw an exception otherwise.

From the above example, you can see that instantiating an Index object provides a reference to that index, even without saving it.

// These two objects reference the same index.
// Key/values added to one can be queried from the other.
$planetIndex = new Everyman\Neo4j\Index\NodeIndex($client, 'planets');
$otherIndex = new Everyman\Neo4j\Index\NodeIndex($client, 'planets');

Add an Entity to an Index

The following code creates a node, then indexes the node on several key/values:

$shipIndex = new Everyman\Neo4j\Index\NodeIndex($client, 'ships');

$heartOfGold = $client->makeNode()
    ->setProperty('propulsion', 'infinite improbability drive')
    ->save();

// Index the ship on one of its properties
$shipIndex->add($heartOfGold, 'propulsion', $heartOfGold->getProperty('propulsion'));

// Index on arbitrary keys/values
$shipIndex->add($heartOfGold, 'captain', 'Zaphod');
$shipIndex->add($heartOfGold, 'computer', 'Eddie');

// Index an entity more than once on the same key
$shipIndex->add($heartOfGold, 'captain', 'Trillian');

Each Index::add() operation will return true if the entitiy was successfully indexed, and throw an exception otherwise.

Entities do not have to be indexed on one of their properties. An entity can be indexed on any arbitrary key/value pair. The value must be a scalar (string or numeric) value.

Removing an Entity from an Index

An entity can be removed from an index on several levels: by specific a key/value pair; by all values for a key; and for all keys. The following code demonstrates each level:

// Remove node with a specific key/value
$shipIndex->remove($heartOfGold, 'computer', 'Eddie');

// Remove node for all values of a given key
$shipIndex->remove($heartOfGold, 'captain');

// Remove node for all keys/values
$shipIndex->remove($heartOfGold);

Each Index::remove() operation will return true if the entitiy was successfully removed, and throw an exception otherwise.

Searching Indexes

There are two ways to search an index: exact key/value match and querying using a query language (like Apache Lucene)

Exact match

Searching by an exact match means that the value being searched must exactly equal the value that was indexed.

// Returns an array of matching entities
$matches = $shipIndex->find('captain', 'Zaphod');

// Returns the first matching entity
$match = $shipIndex->findOne('captain', 'Zaphod');

If no matches are found, Index::find() returns an empty array and Index::findOne() returns null. The value being searched must be a scalar (string or numeric) value.

Querying

Indexes can also be queried using Lucene query syntax. This allows searching an index on less strict criteria than an exact match. Here is an example that searches the "ships" index using a wildcard match:

// Returns an array of matching entities
// where the 'propulsion' key's value starts with 'infinite'
// and the captain is 'Zaphod'
$matches = $shipIndex->query('propulsion:infinite* AND captain:Zaphod');

// Returns the first matching entity
$matches = $shipIndex->queryOne('propulsion:infinite* AND captain:Zaphod');

If no matches are found, Index::query() returns an empty array and Index::queryOne() returns null.