Criteria Queries

CriteriaQuery let’s you specify restrictions on objects that the query result must contain. The ODB CriteriaQuery API is very close to the Hibernate Criteria API.

Example of a Criteria Query

public void step3() throws Exception {
    ODB odb = null;
 
    try {
        // Open the database
        odb = ODBFactory.open(ODB_NAME);
 
        IQuery query = new CriteriaQuery(Player.class,     Restrictions.equal("name", "olivier"));
 
        Objects players = odb.getObjects(query);
 
        System.out.println("\nStep 3 : Players with name olivier");
 
        // display each object
        while(players.hasNext()) {
            System.out.println((i + 1) + "\t: " + players.next());
            }
    } finally {
        if (odb != null) {
            // Close the database
            odb.close();
        }
    }
}

All query related code is located in src / org.neodatis.odb.core.query.criteria package

How does it work?

a criteria query is defined by 4 parameters:

  • The class of the objects that must be loaded
  • the criterio to filter objects
  • an order by clause
  • the range of the objects to be returned

the org.neodatis.odb.core.query.execution.CriteriaQueryExecutor first defines the execution plan (CriteriaQueryExecutionPlan). If an index can be used, then the GenericQueryExecutor.executeUsingIndex will be used,If not, the GenericQueryExecutor.executeFullScan Will be used.

The goal of the execution is to get all the possible candidate objects to enter the query result. If no index can be found, a full class scan (all objects will be checked) will be necessary. Then the criteria query is executed against all cadidate objects.
check to optimize the query by reducing the number of candidates.

Optimizations

> object loading

When loading candidate objects to execute query, ODB does not read the entire object nor creates an instance of it, it only reads the attributes that are used in the query (org.neodatis.odb.core.query.criteria.CriteriaQuery.getAllInvolvedFields()) and keep the values in attributes values map (org.neodatis.odb.core.io.AttributeValuesMap). The full object will only be read and instanciated if the query returns true meaning that the object is part of the result.

> query range

While executing a query, one can ask ODB to return a part of the result : from object x to object y. It is very using for paging results.

Order by clause

When using an order clause, ODB used a BTree to guarantee the order of the objects. The criteria query manager computes the key (composed key, CriteriaQueryExecutor.buildOrderByKey()) of the btree based upon the order by clause definitition for each object that must be included in the query result. Then, the key is used to insert the object if the btree.

full scan object loading

To read all the objects of a specific class ODB first gets the ClassInfo of the class from the metamodel.

The ClassInfo is a meta representation of the class. It contains all the info about the class (name, package, attributes, indexes) and some pointers to its objects. ClassInfo holds the number of objects (check why the next release will not keep it anymore), a pointer (the OID) to its first object and a pointer(OID) to its last object. Then each object have a header that contains its oid, its class oid, the oid of the previous object of the same class, the oid of the next object of the same class (see the new odb file format to understand why this will change).

So, in the current release of ODB, to read all the objects of a class, go to the class info, take the oid of the first object, ask ODB the position of the object with the oid, reads the object (header and values), from the header, gets the next object oid,… Untill next object oid is null. Check current odb format file.

Restrictions

Restrictions on objects are build by the org.neodatis.odb.core.query.criteria.Restrictions (which implements IRestrictions) Factory. All the methods of the IRestrictions return objects of type org.neodatis.odb.core.query.criteria.ICriterion.

The ICriterion interface is the standard way to expressed an object restriction. Here the interface definitions:

public interface ICriterion extends Serializable{
    /** To check if an object matches this criterion
     * @param object 
     * @return true if object matches the criteria*/ 
    boolean match(Object object);
 
    /** To be abble to optimize query execution. Get only the field
     involved in teh query instead of getting all the object
     * @return All involved fields in criteria*/
    List getAllInvolvedFields();
    Map getValues();
    /** Gets thes whole query
     * @return The owner query*/
    IQuery getQuery();
    void setQuery(IQuery query);
}

The most important method if the match which will return true if a specific object match the restriction.

Here is the example of the EqualCriterion.match method

    public boolean match(Object valueToMatch) {
        // If it is a AttributeValuesMap, then gets the real value from the map
        // AttributeValuesMap is used to optimize Criteria Query 
        // (reading only values of the object that the query needs to be 
        // evaluated instead of reading the entire object)
        if(valueToMatch instanceof AttributeValuesMap){
            AttributeValuesMap attributeValues = (AttributeValuesMap) valueToMatch;
            valueToMatch = attributeValues.getAttributeValue(attributeName);
        }
 
        if (valueToMatch == null && criterionValue == null) {
            return true;
        }
        return valueToMatch != null && valueToMatch.equals(criterionValue);
    }

The EqualCriterion simply returns true when the value of the criterion is equal to the value of the object.

Here is a list of all classes implementing ICriterion:

ICriterionHierarchy.png

Here are all the methods of the Restrictions factory:

Method Description
equal Returns an EqualCriterion
like to execute a like
ilike To execute a case insentive like
gt A greater than criterion
ge A greater or Equal criterion
lt A lesser than criterion
le A lesser or equal criterio
contain To search in list. Returns true if a list contains a specific element
isNull Returns true if the object is null
isNotNull Returns true if Object is not null
sizeEq Returns true if the size of a list or array is equal to
sizeGt Returns true if the size of a list or array is greater than
sizeGe Returns true if the size of a list or array is greater or equal to
sizeLt Returns true if the size of a list or array is lesser than
sizeLe Returns true if the size of a list or array is lesser or equal to
or To combine criterion with or : return criterio1 or criterio2 or criterion3
and To combine criterion with and : return criterio1 and criterio2 and criterion3
not To negate criterion
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License