As of Protege 3.4 beta, build 108, this built-in library has been replaced by the SQWRL built-in library. To update existing ontologies that use this library, simply change the prefix of any query built-ins from 'query' to 'sqwrl'.    (A3B)

The SWRL Query Built-In Library is one of the SWRLTabBuiltInLibraries. It defines a set of built-ins that can be used in SWRL rules to query OWL ontologies. The built-ins in this library can be used to effectively turn SWRL into a query language. They provide SQL-like operations to format knowledge retrieved from an OWL ontology. The resulting query language does not alter SWRL's semantics and uses the standard presentation syntax supported by the SWRLTab.    (8V8)

This document assumes that the reader is already familiar with SWRL. An introduction can be found here.    (9LS)

These built-ins are defined in the SWRL Query Ontology. It has the default namespace prefix query. A copy of this file can be found the standard Protege-OWL repositories, and can be imported through the 'Import Ontology' option in the Metadata tab.    (9X6)

Basic Queries    (8UI)

Assume we have a simple ontology with classes Person, which has subclasses Male and Female with associated functional properties hasAge and hasName, and a class Car, that can be associated with individual of class Person through the hasCar property.    (8WY)

Here, for example, is a simple SWRL query to extract all known persons in an ontology whose age is less than 25, together with their ages:    (8SW)

This query will return pairs of individuals and ages.    (8WZ)

To list all the cars owned by each person, we can write:    (8SY)

This query will return pairs of individuals and their cars. Assuming hasCar is a non functional property, multiple pairs would be displayed for each individual - one pair for each car that they own.    (8T0)

The select built-in accepts a variable number of arguments. Literal values can also be passed to it. Those values are simply returned as row content. For example, the query:    (91A)

will return with the string "Cars and Persons" as the third column contents of every row in the result.    (91C)

Accessing the Results of Queries    (8UY)

There are two mechanisms provides by the SWRLTab for accessing the results of queries: (1) a Java API that provides a JDBC-like interface called the SWRLQueryAPI, which can be used to retrieve query results in Java application; and (2) a graphical user interface called the SWRLQueryTab that supports interactive querying and results display within the SWRLTab.    (8TA)

Queries and Rules    (8YR)

Rules with query built-ins are not independent of other SWRL rules in an ontology - they operate in conjunction with those rules as part of a rule base. Queries can thus be used to retrieve knowledge inferred by other rules.    (8YX)

Assume, for example, that we define the person subclass Adult and attach the functional property hasAge to persons and write the following rule to classify persons older than 17 as adults:    (8YT)

We can then write a query to list all the adults in an ontolgy as follows:    (8YV)

While, one could write a single rule that simply retrieved all persons older than 17 years old, the use of an intermediate class assists readability and permits reuse of the intermediate concept in other rules. While subqueries are not possible in SWRL queries, these intermediate concepts can be used to provide an effective equivalent.    (8YY)

Counting    (8UK)

Basic counting is also supported by the query built-in library. A built-in called count provides this functionality. It takes a single argument. If we wished to, say, get a count of the number of cars owned by a individuals in an ontology, we could write the following query:    (8T1)

This query would return a list of individuals and counts, with one row for each individual together with a count of the number of cars that they own. Individuals that have no cars would not be matched by this query.    (8TD)

A similar query to count the number of cars owned by persons in an ontology can be written as:    (8UL)

If we wish to simply count the number of cars in an ontology irrespective of whether they have owners or not, we can write:    (8WW)

When the count built-in is used in a query, all variables mentioned in the select built-in are effectively coalesced - that is, all value equivalent rows are merged. For example, the following query will return a list of all person names in an ontology:    (912)

If more than one person has a particular name it will be returned multiple times. If, however, we wish to count the number of times each person name occurs in an ontology, we can do the following:    (914)

Every duplicate name will be grouped and the count built-in will keep track of the number of occurrences of each name.    (916)

This process is analogous to SQL's GROUP BY clause - the only difference being that grouping is implicit.    (917)

Clearly, counting operates on the result itself - not on the underlying ontology.    (8Z0)

Aggregation    (8UO)

Basic aggregation is also supported. Four built-ins called min, max, sum, and avg provide this functionality. Aggregation built-ins take a single argument which must represent a numeric type. For example, a query to return the average age of persons in an ontology (for which an age is known) can be written as:    (8UP)

Similarly, a query to return the maximum age of a person in an ontology can be written as:    (8UR)

Any numeric variable not passed to a select built-in can be aggregated. Variables that have already been passed to a select built-in cannot be aggregated - an error will be generated by the query library if an attempt is made to use them in this way.    (8TH)

As with the count built-in above, the aggregation process is similar to grouping in SQL.    (918)

Ordering of Results    (8VN)

Results can be ordered using the orderBy and orderByDescending built-ins. For example, to extend the earlier query that returns a count of the number of cars owned by each person to order the results by each person's name, we can write:    (8W0)

The orderBy and orderByDescending built-ins take one or more variables as arguments. All such arguments must have been used in a select, count, or aggregate built-in in the same query.    (98U)

So, for example, we can rewrite the previous query to order the results but the number of cars owned by each person in descending order as follows:    (98V)

If an attempt is made to mix ascending and descending ordering in the same rule an error will be generated.    (8YZ)

Eliminating Duplicate Rows    (92C)

Duplicate rows can be eliminated by using the selectDistinct built-in. For example, to retrieve all the distinct names of persons in an ontology, we can write:    (92D)

Naming of Result Columns    (91D)

The columns in a result are automatically named. Selected columns are named after the relevant variable; aggregate columns are named after the aggregate function name with the aggregated variable in parentheses; and, literal values are enclosed by square braces. So, for example, the following query:    (91E)

will generate three columns with names "?name", "[Number of cars]", and "count(?c)".    (91G)

A columnNames built-in is provided to specify user-defined column names. This built-in takes a list of string arguments and uses them as the names of the result column. For example, if we wish to explicitly name the result columns in the previous query, we can write:    (91H)

The columnNames arguments are used left-to-right to assign names to columns. If fewer names than result columns are supplied, the remaining columns will keep their automatically generated names. If more names are supplied than are present in the query, the excess names will be ignored.    (91J)

Interoperation with other Built-In Libraries    (8UZ)

Query built-ins can be used freely with other built-in libraries. For example, to retrieve the name of all males in an ontology and prepend the title "Mr." to each name, we can use Core SWRL Built-in stringConcat as follows:    (8W2)

Using the TBox Query Library with query built-ins allows the writing of queries that ask questions about the classes and properties in an OWL ontology. For example, a query that returns all the direct subclasses of the Person class can be written as follows:    (8VX)

To retrieve all properties (both direct and indirect) of the hasName property, one can write:    (8VY)

The ability to freely use built-ins in a query provides a means of continuously expanding the power of the query language.    (8W3)

Semantics of Query Built-ins    (8UU)

The query built-ins operate on known individuals in the currently loaded OWL ontology - they thus effectively adopt the closed world assumption. It is very important to note that the built-ins provide no way of accessing the information they accumulate from within a rule so the closed world results cannot be written back back to the ontology. There is no way, for example, to insert the result of a computed aggregate count back into the ontology. Such a mechanism could invalidate OWL's open world assumption and lead to nonmonotonicity.    (8VZ)

The query built-ins do not look like normal SWRL built-ins. Unlike most built-ins, they do not evaluate their arguments and return true if the arguments satisfy some predicate. Instead, they act as accumulators and build up data structures outside of an ontology.    (98X)

Repeated use of the same query built-in in a rule is possible. For example, one could use the select built-in twice, as in the following fragment:    (8VC)

Such usage is equivalent to a single invocation of select with all four parameters.    (8VE)

More complicated invocation ordering is also possible. For example, the invocation    (8VF)

is perfectly valid. Semantically, this is equivalent to:    (8VH)

However, the order of the data in the result structure will be different for each case - variable data ordering is controlled by the left-to-right ordering of arguments in the built-ins.    (8VK)

Examples    (9AC)

All the SWRLTabBuiltInLibraries have an example section on their associated Wiki page describing their use with with the query built-ins. See here and here, for example.    (9AD)