Using Queries
Learn about some aspects of using queries to your application in Oracle NoSQL Database.
To execute your query, you use the NoSQLHandle.query()
API.
SELECT
query to read data from your
table:/* QUERY a table named "users", using the primary key field "name".
* The table name is inferred from the query statement.
*/
QueryRequest queryRequest = new QueryRequest().
setStatement("SELECT * FROM users WHERE name = \"Taylor\"");
/* Queries can return partial results. It is necessary to loop,
* reissuing the request until it is "done"
*/
do {
QueryResult queryResult = handle.query(queryRequest);
/* process current set of results */
List<MapValue> results = queryResult.getResults();
for (MapValue qval : results) {
//handle result
}
} while (!queryRequest.isDone());
When using queries, be aware of the following considerations:
-
You can use prepared queries when you want to run the same query multiple times. When you use prepared queries, the execution is more efficient than starting with a query string every time. The query language and API support query variables to assist with the reuse.
For example, to execute a SELECT
query to read data from
your table using a prepared statement:
/* Perform the same query using a prepared statement. This is more
* efficient if the query is executed repeatedly and required if
* the query contains any bind variables.
*/
String query = "DECLARE $name STRING; " +
"SELECT * from users WHERE name = $name";
PrepareRequest prepReq = new PrepareRequest().setStatement(query);
/* prepare the statement */
PrepareResult prepRes = handle.prepare(prepReq);
/* set the bind variable and set the statement in the QueryRequest */
prepRes.getPreparedStatement()
.setVariable("$name", new StringValue("Taylor"));
QueryRequest queryRequest = new QueryRequest().setPreparedStatement(prepRes);
/* perform the query in a loop until done */
do {
QueryResult queryResult = handle.query(queryRequest);
/* handle result */
} while (!queryRequest.isDone());
borneo.NoSQLHandle.query()
method. For example, to execute a SELECT query to read data from your table, a
borneo.QueryResult
contains a list of results. And if the
borneo.QueryRequest.is_done()
returns False, there may be more results,
so queries should generally be run in a loop. It is possible for single request to return
no results but the query still not done, indicating that the query loop should continue.
For
example:from borneo import QueryRequest
# Query at table named 'users" using the field 'name' where name may match
# 0 or more rows in the table. The table name is inferred from the query
statement = 'select * from users where name = "Jane"'
request = QueryRequest().set_statement(statement)
# loop until request is done, handling results as they arrive
while True: result = handle.query(request)
# handle results
handle_results(result)
# do something with results
if request.is_done(): break
- Oracle NoSQL Database provides the ability to prepare queries for execution and reuse. It is recommended that you use prepared queries when you run the same query for multiple times. When you use prepared queries, the execution is much more efficient than starting with a query string every time. The query language and API support query variables to assist with query reuse.
- The
borneo.QueryRequest
allows you to set the read consistency for a query as well as modifying the maximum amount of resource (read and write) to be used by a single request. This can be important to prevent a query from getting throttled because it uses too much resource too quickly.
from borneo import PrepareRequest, QueryRequest
# Use a similar query to above but make the name a variable
statement = 'declare $name string
select * from users where name = $name'
prequest = PrepareRequest().set_statement(statement)
presult = handle.prepare(prequest)
# use the prepared statement, set the variable
pstatement = presult.get_prepared_statement()
pstatement.set_variable('$name', 'Jane')
qrequest = QueryRequest().set_prepared_statement(pstatement)
# loop until qrequest is done, handling results as they arrive
while True:
# use the prepared query in the query
request qresult = handle.query(qrequest)
# handle results
handle_results(qresult)
# do something with results
if qrequest.is_done(): break
# use a different variable value with the same prepared query
pstatement.set_variable('$name', 'another_name')
qrequest = QueryRequest().set_prepared_statement(pstatement)
# loop until qrequest is done, handling results as they arrive
while True:
# use the prepared query in the query
request qresult = handle.query(qrequest)
# handle results
handle_results(qresult)
# do something with results
if qrequest.is_done(): break
Client.Query
function. For
example, to execute a SELECT
query to read data from your
table:prepReq := &nosqldb.PrepareRequest{
Statement: "select * from users",
}
prepRes, err := client.Prepare(prepReq)
if err != nil {
fmt.Printf("Prepare failed: %v\n", err)
return
}
queryReq := &nosqldb.QueryRequest{
PreparedStatement: &prepRes.PreparedStatement,
}
var results []*types.MapValue
for {
queryRes, err := client.Query(queryReq)
if err != nil {
fmt.Printf("Query failed: %v\n", err)
return
}
res, err := queryRes.GetResults()
if err != nil {
fmt.Printf("GetResults() failed: %v\n", err)
return
}
results = append(results, res...)
if queryReq.IsDone() {
break
}
}
Queries should generally be run in a loop and check
QueryRequest.IsDone()
to determine if the query completes.
It is possible for a single request to return no results but still have
QueryRequest.IsDone()
evaluated to false, indicating that
the query loop should continue.
- Oracle NoSQL Database provides the ability to prepare queries for execution and reuse. It is recommended that you use prepared queries when you run the same query multiple times. When you use prepared queries, the execution is much more efficient than starting with a query string every time. The query language and API support query variables to assist with query reuse.
- The
nosqldb.QueryRequest
allows you to set the read consistency for a query (via theQueryRequest.Consistency
field), as well as modifying the maximum amount of resources (read and write, via theQueryRequest.MaxReadKB
andQueryRequest.MaxWriteKB
fields) to be used by a single request. This can be important to prevent a query from getting throttled because it uses too many resources too quickly.
query
method. This method returns
returns Promise
of QueryResult
which is plain
JavaScript object that contains an Array of resulting rows as well as
continuation key. The amount of data returned by the query is limited by the
system default and could be further limited by setting
maxReadKB
property in the opt argument of
query
, which means that one invocation of
query
method may not return all available results. This
situation is dealt with by using continuationKey
property.
Not-null continuation key means that more query results may be available. This
means that queries should generally run in a loop, looping until continuation
key becomes null. Note that it is possible for rows to be empty yet have
not-null continuationKey
, which means the query loop should
continue. In order to receive all the results, call query
in a
loop. At each iteration, if non-null continuation key is received in
QueryResult
, set continuationKey
property
in the opt
argument for the next
iteration:const NoSQLClient = require('oracle-nosqldb').NoSQLClient;
.....
const client = new NoSQLClient('config.json');
async function queryUsersTable() {
const opt = {};
try {
do {
const result = await client.query('SELECT * FROM users', opt);
for(let row of result.rows) {
console.log(row);
}
opt.continuationKey = result.continuationKey;
} while(opt.continuationKey);
} catch(error) {
//handle errors
}
}
- The Oracle NoSQL Database provides the ability to prepare queries for execution and reuse. It is recommended that you use prepared queries when you run the same query for multiple times. When you use prepared queries, the execution is much more efficient than starting with a query string every time. The query language and API support query variables to assist with query reuse.
- Using opt argument of
query
allows you to set the read consistency for query as well as modifying the maximum amount of data it reads in a single call. This can be important to prevent a query from getting throttled.
prepare
method to prepare the query. This method
returns Promise of PreparedStatement
object. Use set method to
bind query variables. To run prepared query, pass
PreparedStatement
to the query or
queryIterable
instead of the statement
string.const NoSQLClient = require('oracle-nosqldb').NoSQLClient;
.....
const client = new NoSQLClient('config.json');
async function queryUsersTable() {
const statement = 'DECLARE $name STRING; SELECT * FROM users WHERE ' +
'name = $name';
try {
let prepStatement = await client.prepare(statement);
const opt = {};
// Set value for $name variable
prepStatement.set('$name', 'Taylor');
do {
let result = await client.query(prepStatement);
for(let row of result.rows) {
console.log(row);
}
opt.continuationKey = result.continuationKey;
} while (opt.continuationKey);
// Set different value for $name and re-execute the query
prepStatement.set('$name', 'Jane');
do {
let result = await client.query(prepStatement);
for(let row of result.rows) {
console.log(row);
}
opt.continuationKey = result.continuationKey;
} while (opt.continuationKey);
} catch(error) {
//handle errors
}
}
QueryAsync
method or call
GetQueryAsyncEnumerable
method and iterate over the resulting async
enumerable. You may pass options to each of these methods as QueryOptions.
QueryAsync
method return
Task<QueryResult<RecordValue>>
. QueryResult contains query
results as a list of RecordValue instances, as well as other information. When your query
specifies a complete primary key (or you are executing an INSERT statement), it is
sufficient to call QueryAsync
once.var client = new NoSQLClient("config.json");
try {
var result = await client.QueryAsync(
"SELECT * FROM users WHERE id = 1");
// Because we select by primary key, there can be at most one record.
if (result.Rows.Count>0) {
Console.WriteLine("Got record: {0}.", result.Rows[0]);
}
else {
Console.WriteLine("Got no records.");
}
}
catch(Exception ex) {
// handle exceptions
}
The amount of data returned by the query is limited by the system. It could also be
further limited by setting MaxReadKB
property of
QueryOptions
. This means that one invocation of
QueryAsync
may not return all available results. This situation is
dealt with by using continuation key. Non-null ContinuationKey in
QueryResult
means that more more query results may be available. This
means that queries should run in a loop, looping until the continuation key becomes
null
.
QueryResult.Rows
is empty) yet have not-null continuation key, which
means that the query should continue looping. To continue the query, set
ContinuationKey
in the QueryOptions
for the next call
to QueryAsync
and loop until the continuation key becomes null.
The following example executes the query and prints query
results:var client = new NoSQLClient("config.json");
var options = new QueryOptions();
try {
do {
var result = await client.QueryAsync(
"SELECT id, name FROM users ORDER BY name",
options);
foreach(var row of result.Rows) {
Console.WriteLine(row);
}
options.ContinuationKey = result.ContinuationKey;
}
while(options.ContinuationKey != null);
}
catch(Exception ex){
// handle exceptions
}
GetQueryAsyncEnumerable
. It returns an instance of
AsyncEnumerable<QueryResult>
that can be iterated over. Each
iteration step returns a portion of the query results as
QueryResult.var client = new NoSQLClient("config.json");
try {
await foreach(var result in client.GetQueryAsyncEnumerable(
"SELECT id, name FROM users ORDER BY name"))
{
foreach(var row of result.Rows) {
Console.WriteLine(row);
}
}
}
catch(Exception ex){
// handle exceptions
}
Oracle NoSQL Database provides the ability to prepare queries for execution and reuse. It is recommended that you use prepared queries when you run the same query for multiple times. When you use prepared queries, the execution is much more efficient than starting with a SQL statement every time. The query language and API support query variables to assist with query reuse.
PrepareAsync
to prepare the query. This method returns
Task<PreparedStatement>
. PreparedStatement
allows you to set query variables. The query methods QueryAsync
and
GetQueryAsyncEnumerable
have overloads that execute prepared queries by
taking PreparedStatement
as a parameter instead of the SQL statement. For
example:var client = new NoSQLClient("config.json");
try {
var sql = "DECLARE $name STRING; SELECT * FROM users WHERE " +
"name = $name";
var preparedStatement = await client.PrepareAsync(sql);
// Set value for $name variable and execute the query
preparedStatement.Variables["$name"] = "Taylor";
await foreach(var result in client.GetQueryAsyncEnumerable(
preparedStatement)) {
foreach(var row of result.Rows) {
Console.WriteLine(row);
}
}
// Set different value for $name and re-execute the query.
preparedStatement.Variables["$name"] = "Jane";
await foreach(var result in client.GetQueryAsyncEnumerable(
preparedStatement)) {
foreach(var row of result.Rows) {
Console.WriteLine(row);
}
}
}
catch(Exception ex){
// handle exceptions
}
NosqlTemplate runQuery()
,
runQueryJavaParams()
,
runQueryNosqlParams()
. For details, see SDK for Spring Data API
Reference.Note:
First, create theAppConfig
class that extends
AbstractNosqlConfiguration
class to provide the
connection details of the Oracle NoSQL Database. For more details, see Obtaining a NoSQL
connection.
In this section, you use the derived queries. For more details on the derived queries, see Derived Queries.
UsersRepository
interface. This interface extends the NosqlRepository
interface and provides the entity class and the data type of the primary key in that class as parameterized types to the NosqlRepository
interface. The NosqlRepository
interface provides methods that are used to retrieve data from the database.import com.oracle.nosql.spring.data.repository.NosqlRepository;
/* The Users is the entity class and Long is the data type of the primary key in the Users class.
This interface provides methods that return iterable instances of the Users class. */
public interface UsersRepository extends NosqlRepository<Users, Long> {
/* Search the Users table by the last name and return an iterable instance of the Users class.*/
Iterable<Users> findByLastName(String lastname);
}
Users
table with the last name as required and print the values to the output from the object.@Autowired
private UsersRepository repo;
System.out.println("\nfindBylastName: Willard");
/* Use queries to find by the last Name. Search the Users table by the last name and return an iterable instance of the Users class.*/
allusers = repo.findByLastName("Willard");
for (Users s: allusers) {
System.out.println(" User: " + s);
}
findBylastName: Willard
User: Users{id=2, firstName=Angela, lastName=Willard}