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.
Among the consequences of this divergence from the relational index idea are:
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.
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 an email management 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 InversionThe 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.)