The MarkLogic Optic API is implemented in JavaScript, XQuery, REST, and Java. A general overview and the JavaScript and XQuery implementations of the Optic API is described in Optic API for Multi-Model Data Access in the Application Developer's Guide. This chapter describes the Java Client implementation of the Optic API, which is very similar in structure to the JavaScript version of the Optic API.
This chapter has the following main sections:
The Optic Java Client API provides classes to support building a plan on the client, executing the plan on the server, and processing the response on the client.
On the server, the Optic API can yield a row that satisfies any of several common use cases:
The second use case can take advantage of document joins or constructor expressions. The third use case can take advantage of document joins.
On the client, the Optic Java Client API can consume a set of rows in one of the following ways:
A structured value in a format alien to the response format is encoded as a string. In particular, when getting a CSV payload, a JSON or XML column value is encoded as a string. Similarly, when getting a JSON payload or row, an XML value is encoded as a string (and vice versa).
The Optic Java Client communicates with a REST App Server on MarkLogic.
Optic
, on a server named MLserver
, you can simply enter:curl -X POST --anyauth -u admin:admin -H "Content-Type:application/json" \ -d '{ "rest-api": {"name": "Optic"} }' \ http://MLserver:8002/v1/rest-apis
The Optic
App Server will be assigned an unused port number and all of the required forests and databases will be created for it. The Optic
database created for you will use the default Schemas
database. However, you should create a unique schemas database and assign it to the Optic
database.
To run the examples described in this chapter, do the following:
Optic
) rather than the one used in the procedure.Optic
database.The following packages implement the Optic features in the Java API:
See the MarkLogic Java API JavaDoc reference for details.
The Java Optic API is similar to the server-side JavaScript and XQuery implementations of the Optic API described in Optic API for Multi-Model Data Access in the Application Developer's Guide. This chapter describes the Java Client implementation of the Optic API, which is similar in structure.
The Optic API for Multi-Model Data Access chapter in the Application Developer's Guide contains the following main topics of interest to Java Optic developers:
The *Val interfaces represent client-side values typed with server data types. For example, the PlanBuilder.xs.decimal
method constructs a client value with an xs.decimal
data type.
The *Expr interfaces represent server expressions typed with server data types. For example, the PlanBuilder.fn.formatNumber
method constructs a server expression to format the result of a numeric expression as a string expression.
Server expressions executed to produce the boolean expression for a where
operation or the expression assigned to a column by the PlanBuilder.as
function can take columns as arguments. The function call calculates the result of the expression for each row using the values of the columns in the row. For example, if the first argument to PlanBuilder.fn.formatNumber
is a column, the formatted string will be produced for each row with the value of the column. The column must have a value in each row with the data type required in the expression.
The API provides some overloads for typical literal arguments of expression functions as a convenience.
The com.marklogic.client.type
package has the marker interfaces for the server data types.
Some functions can take multiple values or expressions for a parameter. Such parameters have a sequence data type. A sequence data type can take either a single item of the data type or a sequence of the data type. The API provides constructor functions that take a varargs of items of the appropriate data type and return the sequence.
For instance, PlanBuilder.pattern
takes a sequence for the subject, predicate, and object parameters.
The call can pass either one PlanTriplePosition
instance (an XsAnyAtomicTypeVal
, PlanColumn
, or PlanParamExpr
object) as the subject or use PlanBuilder.subject
to construct a sequence of such objects to pass as the subject.
RowRecord
provides the getKind
metadata method for discovering the ColumnKind
of a column in the current row (ATOMIC_VALUE, CONTENT, or NULL).
For an ATOMIC_VALUE column, the getDatatype
metadata method reports the atomic data type.
You can call a get*
getter to cast the value to the appropriate primitive or to a *Val type.
For a CONTENT column, the getContentFormat
and getContentMimetype
metadata methods report the format and mime type. The caller can pass the appropriate handle to the getContent
getter to read the JSON, XML, binary, or text content (consistent with the Java API elsewhere).
The following two examples are based on documents and template views described in the Creating Template Views chapter in the SQL Data Modeling Guide.
List all of the employees in order of ID number.
package Optic; import com.marklogic.client.DatabaseClient; import com.marklogic.client.DatabaseClientFactory; import com.marklogic.client.io.StringHandle; import com.marklogic.client.expression.PlanBuilder; import com.marklogic.client.expression.PlanBuilder.ModifyPlan; import com.marklogic.client.row.RowManager; public class optic4 { public static void main(String[] args) { DatabaseClient db = DatabaseClientFactory.newClient( "localhost", 8000, new DatabaseClientFactory.DigestAuthContext("admin", "admin") ); RowManager rowMgr = db.newRowManager(); PlanBuilder p = rowMgr.newPlanBuilder(); ModifyPlan plan = p.fromView("main", "employees") .select("EmployeeID", "FirstName", "LastName") .orderBy("EmployeeID") .offsetLimit(0, 25); System.out.println( rowMgr.resultDoc(plan, new StringHandle().withMimetype("text/csv")).get() ); return; } }
Return the ID and full name for the employee with an EmployeeID of 3.
package Optic; import com.marklogic.client.DatabaseClient; import com.marklogic.client.DatabaseClientFactory; import com.marklogic.client.io.StringHandle; import com.marklogic.client.expression.PlanBuilder; import com.marklogic.client.expression.PlanBuilder.ModifyPlan; import com.marklogic.client.row.RowManager; import com.marklogic.client.type.XsIntVal; public class optic { public static void main(String[] args) { DatabaseClient db = DatabaseClientFactory.newClient( "MLserver", 8000, new DatabaseClientFactory.DigestAuthContext("admin", "admin") ); RowManager rowMgr = db.newRowManager(); PlanBuilder p = rowMgr.newPlanBuilder(); XsIntVal EmployeeID = p.xs.intVal(3); ModifyPlan plan = p.fromView("main", "employees") .where(p.eq(p.col("EmployeeID"), EmployeeID)) .select("EmployeeID", "FirstName", "LastName") .orderBy("EmployeeID"); System.out.println( rowMgr.resultDoc(plan, new StringHandle().withMimetype("text/csv")).get() ); return; } }
The following example returns a list of the people who were born in Brooklyn in the form of a table with two columns, person
and name
. This is executed against the example dataset described in Loading Triples in the Semantics Developer's Guide. This example is the Java equivalent of the last JavaScript example described in fromView Examples in the Optic API for Multi-Model Data Access chapter in the Application Developer's Guide.
package Optic; import com.marklogic.client.DatabaseClient; import com.marklogic.client.DatabaseClientFactory; import com.marklogic.client.DatabaseClientFactory.DigestAuthContext; import com.marklogic.client.io.StringHandle; import com.marklogic.client.expression.PlanBuilder; import com.marklogic.client.row.RowManager; import com.marklogic.client.type.PlanColumn; public class optic2 { public static void main(String[] args) { DatabaseClient db = DatabaseClientFactory.newClient( "localhost", 8000, new DigestAuthContext("admin", "admin") ); RowManager rowMgr = db.newRowManager(); PlanBuilder p = rowMgr.newPlanBuilder(); PlanBuilder.Prefixer foaf = p.prefixer("http://xmlns.com/foaf/0.1"); PlanBuilder.Prefixer onto = p.prefixer("http://dbpedia.org/ontology"); PlanBuilder.Prefixer resource = p.prefixer("http://dbpedia.org/resource"); PlanColumn person = p.col("person"); PlanBuilder.QualifiedPlan plan = p.fromTriples( p.pattern(person, onto.iri("birthPlace"), resource.iri("Brooklyn")), p.pattern(person, foaf.iri("name"), p.col("name")) ); System.out.println( rowMgr.resultDoc(plan, new StringHandle().withMimetype("text/csv")).get() ); return; } }