Inversion and Indexes

Previous Next

Relational Indexes vs EAV

(Note that 'index' here does not refer to the Index component type.)

The term in the InfinityDB 'Entity-Attribute-Value' EAV model for the equivalent of a relational index is an inversion. It is a superset of the index concept, because the index itself, rather than being a separate, invisible performance enhancer, is a 'first-class-citizen', so it has its own EntityClass. If you still want to think about indexes as being separate from the relations that they apply to, then just mentally separate the EntityClasses that represent relations from those that represent Indexes.

There is actually no concept of an index in EAV at all, and this may be the one thing that really distinguishes it from the relational model, aside from the capability of having complex values like multi-valued Attributes.

Definition of Inversion

Inversions can be constructed using a simple pattern. In the simplest system, they can be maintained by the programmer when Items are inserted or deleted from the EntityClass being indexed. Here is how:
	static final EntityClass PERSON = new EntityClass(0);
	static final EntityClass CREDIT_CARD = new EntityClass(1);
	static final Attribute CARD_NUMBER = new Attribute(0); // inverse of below
	static final Attribute CARD_HOLDER_NAME = new Attribute(1); // inverse of above
	
	String personName = "jane";
	long cardNumber = 91838103;
	cu.clear().append(PERSON).append(personName).append(CARD_NUMBER).append(cardNumber);
	db.insert(cu);
	// now manually maintain the index or 'Inversion'.
	cu.clear().append(CREDIT_CARD).append(cardNumber).append(CARD_HOLDER_NAME).append(personName);
	db.insert(cu);
This pair of Items constitute a single statement of fact, looked at from two points of view. They either both belong in the db or neither belong in the db. The code that maintains the index has to know whenever an Item is inserted whether an inverse for that Item is expected to match it in the db. The CARD_NUMBER Attribute is called the inverse of the CARD_HOLDER_NAME Attribute, and vice versa.

From the relational point of view, PERSON together with CARD_NUMBER could be considered an index over the CREDIT_CARD 'relation'. Or, CREDIT_CARD together with CARD_HOLDER_NAME could be considered an index over the PERSON 'relation'. The capability of having multi-valued Attributes is essential to the whole idea of inversion.

The Inversion Class

There is a lot of functionality in the EntityClass, Attribute, and Inversion classes specifically to help with the inversion maintenance problem. Please see the javadoc there. It is possible to declare at runtime that pairs of Attributes are inverses, and have the inversion automatically maintained by using various methods on EntityClass, Attribute, and Inversion to do modification. For example, if a particular EntityClass knows the set of Attributes attached to it and each of their inverses, then it can automatically delete all Attributes and their inverses if a given Entity is deleted using EntityClass.delete(ItemSpace db, Cu cuEntity). To declare that two Attributes are inverses, you can just construct an Inversion, so the job is extremely easy.

Here is some code from a patient visit application:

	static final EntityClass PATIENT_CLASS = new EntityClass(35);
	static final EntityClass VISIT_CLASS = new EntityClass(36);
	static final Attribute VISIT = new Attribute(42);
	static final Attribute PATIENT = new Attribute(43); 
	static Inversion PATIENT_VISIT = new Inversion(
	    PATIENT_CLASS, VISIT, // EntityClass,Att
	    VISIT_CLASS, PATIENT); // EntityClass,Att
	// not necessary but sometimes convenient
	static Inversion VISIT_PATIENT = new Inversion(
	    PATIENT_VISIT); // Just refer to the other Inversion
The above code allows using helper methods on EntityClass and Inversion to automatically maintain the pairing of inverse Items in the db. For example:
     PATIENT_VISIT.insert(db,cuPatient,cuVisit);
will automatically insert both:
	<PATIENT_CLASS, patient,VISIT, visit> and
	<VISIT_CLASS, visit, PATIENT, patient>
Also, you can delete all of the values of an Attribute and their inverses:
	PATIENT_CLASS.clear(db, cuPatient, VISIT);
You can delete an entire Entity including all of the inversions of all of its Attributes:
	PATIENT_CLASS.delete(db, cuPatient);
You can change an Entity to another while maintaining all of the values and their inversions:
	PATIENT_CLASS.changeEntity(db, cuPatientFrom, cuPatientTo, true);
Where the boolean parameter is overWrite, and determines whether to merge the old into the new or to replace the new if present.

Please see the javadoc for EntityClass, Inversion, and Inversion's superclass, Attachment to see the full range of helper methods. The javadoc includes representative source code for most of the methods.

(At some point in the future, metadata in the db may be able to determine the inversion setup in the EntityClasses and Attributes declared as static finals in the application.)

Previous Next


Copyright © 1997-2006 Boiler Bay.