A Pilosa URI has the ${SCHEME}://${HOST}:${PORT} format:
- Scheme: Protocol of the URI. Default:
http. - Host: Hostname or ipv4/ipv6 IP address. Default: localhost.
- Port: Port number. Default:
10101.
All parts of the URI are optional, but at least one of them must be specified. The following are equivalent:
http://localhost:10101http://localhosthttp://:10101localhost:10101localhost:10101
A Pilosa URI is represented by the com.pilosa.client.URI class. Below are a few ways to create URI objects:
import com.pilosa.client.URI;
// create the default URI: http://localhost:10101
URI uri1 = URI.defaultURI();
// create a URI from string address
URI uri2 = URI.address("db1.pilosa.com:20202");
// create a URI with the given host and port
URI uri3 = URI.fromHostPort("db1.pilosa.com", 20202);In order to interact with a Pilosa server, an instance of com.pilosa.client.PilosaClient should be created. The client is thread-safe and uses a pool of connections to the server, so we recommend creating a single instance of the client and reuse it when necessary.
If the Pilosa server is running at the default address (http://localhost:10101) you can create the client with default options using:
PilosaClient client = PilosaClient.defaultClient();To use a custom server address, you can use the withAddress class method:
PilosaClient client = PilosaClient.withAddress("http://db1.pilosa.com:15000");If you are running a cluster of Pilosa servers, you can create a Cluster object that keeps addresses of those servers:
Cluster cluster = Cluster.withHost(
URI.address(":10101"),
URI.address(":10110"),
URI.address(":10111")
);
// Create a client with the cluster
PilosaClient client = PilosaClient.withCluster(cluster);It is possible to customize the behaviour of the underlying HTTP client by passing a ClientOptions object to the withCluster class method:
ClientOptions options = ClientOptions.builder()
.setConnectTimeout(1000) // if can't connect in a second, close the connection
.setSocketTimeout(10000) // if no response received in 10 seconds, close the connection
.setConnectionPoolSizePerRoute(3) // number of connections in the pool per host
.setConnectionPoolTotalSize(10) // number of total connections in the pool
.setRetryCount(5) // number of retries before failing the request
.build();
PilosaClient client = PilosaClient.withCluster(cluster, options);Once you create a client, you can create indexes, fields and start sending queries.
Here is how you would create a index and field:
Schema schema = client.readSchema();
Index index = schema.index("index");
Field field = index.field("field");
client.syncSchema(schema);You can send queries to a Pilosa server using the query method of client objects:
QueryResponse response = client.query(field.row(5));query method accepts an optional argument of type QueryOptions:
QueryOptions options = QueryOptions.builder()
.setColumns(true) // return column data in the response
.build();
QueryResponse response = client.query(field.row(5), options);When a query is sent to a Pilosa server, the server either fulfills the query or sends an error message. In the case of an error, PilosaException is thrown, otherwise a QueryResponse object is returned.
A QueryResponse object may contain zero or more results of QueryResult type. You can access all results using the getResults method of QueryResponse (which returns a list of QueryResult objects),or you can use the getResult method (which returns either the first result or null if there are no results):
QueryResponse response = client.query(field.row(5));
// check that there's a result and act on it
QueryResult result = response.getResult();
if (result != null) {
// act on the result
}
// iterate over all results
for (QueryResult r : response.getResults()) {
// act on the result
}Similarly, a QueryResponse object may include a number of column objects, if setColumns(true) query option was used:
// check that there's a column and act on it
ColumnItem column = response.getColumn();
if (column != null) {
// act on the column
}
// iterate over all columns
for (ColumnItem column : response.getColumns()) {
// act on the column
}QueryResult objects contain:
getRowmethod to retrieve a row result,getCountItemsmethod to retrieve column count per row ID entries returned fromTopNqueries,getCountmethod to retrieve the number of rows per the given row ID returned fromCountqueries.getValuemethod to retrieve the result ofMin,MaxorSumqueries.isChangedmethod returns whether aSetBitorClearBitquery changed a column.
QueryResult result = response.getResult();
RowResult row = result.getRow();
List<Long> columns = row.getColumns();
Map<String, Object> attributes = row.getAttributes();
List<CountResultItem> countItems = result.getCountItems();
long count = result.getCount();
long value = result.getValue();
boolean changed = result.isChanged();Make sure the Pilosa server runs on a TLS address. How To Set Up a Secure Cluster tutorial explains how to do that.
In order to enable TLS support on the client side, the scheme of the address should be explicitly specified as https, e.g.: https://01.pilosa.local:10501
This client library uses the Apache HTTP Library. ClientOptions builder accepts a javax.net.ssl.SSLContext object, which is set to org.apache.http.ssl.SSLContexts.createDefault() by default. If the Pilosa server is using a certificate from a recognized authority, you can use the defaults.
If you are using a self signed certificate, you need to derive from PilosaClient and override the getRegistry method:
public class InsecurePilosaClient extends PilosaClient {
public InsecurePilosaClient(Cluster cluster, ClientOptions options) {
super(cluster, options);
}
@Override
protected Registry<ConnectionSocketFactory> getRegistry() {
HostnameVerifier verifier = new HostnameVerifier() {
@Override
public boolean verify(String hostName, SSLSession session) {
return true;
}
};
SSLContext sslContext = null;
try {
sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
public boolean isTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
return true;
}
}).build();
} catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException e) {
e.printStackTrace();
}
if (sslContext == null) {
throw new RuntimeException("SSL Context not created");
}
SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(
sslContext,
new String[]{"TLSv1.2"}, null, verifier);
return RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
.register("https", sslConnectionSocketFactory)
.build();
}
}