表および索引の作成

表および索引の作成方法について学習します。

表の作成は、アプリケーション開発の最初のステップです。

DDL文の例を次に示します。

/* Create a new table called users */
CREATE TABLE IF NOT EXISTS users(id INTEGER,
 name STRING,
 PRIMARY KEY(id))

/* Create a new table called users and set the TTL value to 4 days */
CREATE TABLE IF NOT EXISTS users(id INTEGER,
 name STRING,
 PRIMARY KEY(id))
USING TTL 4 days
/* Create a new multi-region table called users with two regions, and set the TTL value to 4 days */
CREATE TABLE users(
 id INTEGER,
 name STRING,
 team STRING,
 primary key(id))
USING TTL 4 DAYS IN REGIONS fra, lnd
/* Create a new index called nameIdx on the name field in the users table */
CREATE INDEX IF NOT EXISTS nameIdx ON users(name)

TableRequestとそのメソッドを使用して、表と索引を作成します。TableRequestクラスを使用すると、DDL文をTableRequest.setStatementメソッドに渡すことができます。

/* Create a simple table with an integer key and a single json data
 * field  and set your desired table capacity.
 * Set the table TTL value to 3 days.
 */
String createTableDDL = "CREATE TABLE IF NOT EXISTS users " +
 "(id INTEGER, name STRING, " +
 "PRIMARY KEY(id)) USING TTL 3 days";


TableRequest treq = new TableRequest().setStatement(createTableDDL);
// start the asynchronous operation
TableResult tres = handle.tableRequest(treq);


// The table request is asynchronous, so wait for the table to become active.
TableResult.waitForState(handle, tres.getTableName(),
 TableResult.State.ACTIVE,
 60000, // wait for 60 sec
 1000); // delay in ms for poll 

// Create an index called nameIdx on the name field in the users table.
treq = new TableRequest().setStatement("CREATE INDEX 
  IF NOT EXISTS nameIdx ON users(name)
  ");

// start the asynchronous operation
  handle.tableRequest(treq);

表の一覧を検索します:

表の一覧を取得できます。
ListTablesRequest tablereq = new ListTablesRequest();
String [] tablelis = handle.listTables(tablereq).getTables();
if (tablelis.length == 0)   
   System.out.println("No tables avaiable");
else {  
   System.out.println("The tables available are");   
   for (int i=0;i< tablelis.length; i++)  {    
      System.out.println(tablelis[i]);  
   }
}
表のスキーマもいつでもフェッチできます。
GetTableRequest gettblreq = new GetTableRequest();
gettblreq.setTableName(tableName);
System.out.println("The schema details for the table is " 
+ handle.getTable(gettblreq).getSchema());
DDL文は、borneo.TableRequestクラスを使用して実行されます。borneo.NoSQLHandle.table_request()へのすべてのコールは非同期であるため、結果を確認し、borneo.TableResult.wait_for_completion()をコールして操作が完了するまで待機する必要があります。
#Create a simple table with an integer key and a single 
#json data field and set your desired table capacity. 
#Set the table TTL value to 3 days.
from borneo import TableLimits,
TableRequest statement = 'create table if not exists users(id integer, 
                                              name string,
                                              ' + 'primary key(id) 
                                                 USING TTL 3 DAYS'

request = TableRequest().set_statement(statement)
# assume that a handle has been created, as handle, make the request 
#wait for 60 seconds, polling every 1 seconds
result = handle.do_table_request(request, 60000, 1000) 
# the above call to do_table_request is equivalent to 
# result = handle.table_request(request)
result.wait_for_completion(handle, 60000, 1000)
#Create an index called nameIdx on the name field in the users table.
request = TableRequest().set_statement("CREATE INDEX IF NOT EXISTS nameIdx 
                                        ON users(name)")
# assume that a handle has been created, as handle, make the request 
#wait for 60 seconds, polling every 1 seconds
result = handle.do_table_request(request, 60000, 1000) 
# the above call to do_table_request is equivalent to
# result = handle.table_request(request) 
result.wait_for_completion(handle, 60000, 1000)

表の一覧を検索します:

表の一覧を取得できます。
ltr = ListTablesRequest()
list(str)= handle.list_tables(ltr).getTables()
if list(str).len() = 0 
   print ("No tables available")
else 
   print('The tables available are: ' + list(str))
表のスキーマもいつでもフェッチできます。
request = GetTableRequest().set_table_name(table_name)
result = handle.get_table(request)
print('The schema details for the table is: ' + result.get_schema())
次の例では、整数キーと単一のSTRINGフィールドを持つ単純な表を作成します。表の作成リクエストは非同期です。表の作成が完了するまで待機します。
// Create a simple table with an integer key and a single
// json data field and set your desired table capacity.
// Set the table TTL value to 3 days.
tableName := "users"
stmt := fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s "+
    "(id integer, name STRING, PRIMARY KEY(id) "+
    "USING TTL 3 DAYS)", tableName)

tableReq := &nosqldb.TableRequest{
    Statement: stmt, }
tableRes, err := client.DoTableRequest(tableReq)
if err != nil {
    fmt.Printf("cannot initiate CREATE TABLE request: %v\n", err)
    return
}
_, err = tableRes.WaitForCompletion(client, 60*time.Second, time.Second)
if err != nil {
    fmt.Printf("Error finishing CREATE TABLE request: %v\n", err)
    return
}
fmt.Println("Created table ", tableName)
//Create an index called nameIdx on the name field in the users table
stmt_ind := fmt.Sprintf("CREATE INDEX IF NOT EXISTS nameIdx ON users(name)")
tableReq := &nosqldb.TableRequest{Statement: stmt_ind}
tableRes, err := client.DoTableRequest(tableReq)
if err != nil {
    fmt.Printf("cannot initiate CREATE INDEX request: %v\n", err)
    return
}
_, err = tableRes.WaitForCompletion(client, 60*time.Second, time.Second)
if err != nil {
    fmt.Printf("Error finishing CREATE INDEX request: %v\n", err)
    return
}
fmt.Println("Created index nameIdx ")

表の一覧を検索します:

表の一覧を取得できます。
req := &nosqldb.ListTablesRequest{Timeout: 3 * time.Second,}
res, err := client.ListTables(req)
if len(res.Tables)== 0{
   fmt.Printf("No tables in the given compartment"
   return
}
fmt.Printf("The tables in the given compartment are:\n" )
for i, table := range res.Tables {
   fmt.Printf(table)
}
表のスキーマもいつでもフェッチできます。
req := &nosqldb.GetTableRequest{
TableName: table_name, Timeout: 3 * time.Second, }
res, err := client.GetTable(req)
fmt.Printf("The schema details for the table is:state=%s, 
   limits=%v\n", res.State,res.Limits)

表DDL文は、tableDDLメソッドによって実行されます。NoSQLClientクラスの他のほとんどのメソッドと同様に、このメソッドは非同期で、TableResultのPromiseを返します。TableResultは、DDL操作のステータス(TableState、名前、スキーマ、TableLimitなど)を含むプレーンJavaScriptオブジェクトです。

tableDDLメソッドは、指定されたDDL操作のみを基礎となるストアで起動し、完了を待機しないことに注意してください。結果のTableResultは、通常、TableState.CREATINGTableState.DROPPINGTableState.UPDATINGなどの中間表の状態の1つを持ちます(後者は、表がALTER TABLE文によって変更されるプロセス中であるか、表の制限が変更されているか、その索引のいずれかが作成または削除されている場合に発生します)。

基礎となる操作が完了すると、表の状態がTableState.ACTIVEまたはTableState.DROPPEDに変更されます(DDL操作がDROP TABLEだった場合は後者)。
const NoSQLClient = require('oracle-nosqldb').NoSQLClient;
const TableState = require('oracle-nosqldb').TableState;
const client = new NoSQLClient('config.json');

async function createUsersTable() {
    try {
        const statement = 'CREATE TABLE IF NOT EXISTS users(id INTEGER, ' +
            'name STRING, PRIMARY KEY(id))';

let result = await client.tableDDL(statement);
        result = await client.forCompletion(result);
        console.log('Table users created');
    } catch(error) {
        //handle errors
    }
}
前述のコールが返されると、結果は操作の最終状態を反映します。または、完全なオプションを使用するには、前述のtry-catchブロックのコードを次のように置き換えます。
const statement = 'CREATE TABLE IF NOT EXISTS users(id INTEGER, ' +
        'name STRING, PRIMARY KEY(id))';

let result = await client.tableDDL(statement,
        complete: true
    });
    console.log('Table users created');
// Create an index called nameIdx on the name field in the users table.
try {
   const statement = 'CREATE INDEX IF NOT EXISTS nameIdx ON users(name))';
   let result = await client.tableDDL(statement);
   result = await client.forCompletion(result);
   console.log('Index nameIdx created');
} catch(error){
  //handle errors 
}

表の一覧を検索します:

表の一覧を取得できます。
let varListTablesResult = await client.listTables();
console.log("The tables in the given compartment are:")
{res.send(varListTablesResult)}
表のスキーマもいつでもフェッチできます。
let resExistingTab = await client.getTable(tablename);
{ await client.forCompletion(resExistingTab);}
console.log("The  schema details for the table is:")
{ res.send(resExistingTab.schema)}

表を作成し、他のデータ定義言語(DDL)文(表の作成、変更および削除、索引の作成および削除など)を実行するには、ExecuteTableDDLAsyncおよびExecuteTableDDLWithCompletionAsyncメソッドを使用します。メソッドExecuteTableDDLAsyncおよびExecuteTableDDLWithCompletionAsyncは、Task<TableResult>を返します。TableResultインスタンスには、TableStateや表スキーマなどのDDL操作のステータスが含まれます。これらの各メソッドには、複数のオーバーロードがあります。特に、DDL操作のオプションをTableDDLOptionsとして渡すことができます。

これらは長時間実行される可能性があることに注意してください。メソッドExecuteTableDDLAsyncは、サービスによって指定されたDDL操作のみを起動し、その完了を待機しません。返されるTableResultインスタンスでWaitForCompletionAsyncをコールすることで、表DDL操作の完了を非同期で待機できます。
var client = new NoSQLClient("config.json");
try { 
  var statement = "CREATE TABLE IF NOT EXISTS users(id INTEGER,"
    + "name STRING, PRIMARY KEY(id))";

var result = await client.ExecuteTableDDLAsync(statement);
  await result.WaitForCompletionAsync(); 
  Console.WriteLine("Table users created."); 
} catch(Exception ex) {
   // handle exceptions
}
WaitForCompletionAsyncは、操作の完了を反映するようにコール元のTableResultインスタンスを変更することに注意してください。
または、ExecuteTableDDLWithCompletionAsyncを使用することもできます。try-catchブロックの文を次のように置き換えます。
var statement = "CREATE TABLE IF NOT EXISTS users(id INTEGER,"
    + "name STRING, PRIMARY KEY(id))"; 


await client.ExecuteTableDDLWithCompletionAsync(statement);
Console.WriteLine("Table users created.");

表の一覧を検索します:

表の一覧を取得できます。
varresult = await client.ListTablesAsync(); 
console.WriteLine("The tables in the given compartment are:") 
foreach(var tableName inresult.TableNames){
   Console.WriteLine(tableName);
}

Springデータ・アプリケーションでは、@NosqlTable.autoCreateTablefalseに設定されていないかぎり、エンティティの初期化時に表がアプリケーションの開始時に自動的に作成されます。

永続化するUsersエンティティ・クラスを作成します。このエンティティ・クラスはOracle NoSQL Databaseの表を表しています。また、このエンティティのインスタンスはその表の行に対応します。

IDフィールドを示す@NosqlId注釈を指定します。generated=true属性は、IDが自動生成されることを指定します。

IDフィールド・タイプが文字列の場合は、UUIDが使用されます。IDフィールド・タイプがintまたはlongの場合は、"GENERATED ALWAYS as IDENTITY (NO CYCLE)"シーケンスが使用されます。

import com.oracle.nosql.spring.data.core.mapping.NosqlId;
import com.oracle.nosql.spring.data.core.mapping.NosqlTable;
 
public class Users {
    @NosqlId(generated = true)
    long id;
    String firstName;
    String lastName;
 
    /* public or package-protected constructor is required when retrieving from the database. */
    public Users() {
    }
 
    @Override
    public String toString() {
        return "Users{" +
                "id=" + id + ", " +
                "firstName=" + firstName + ", " +
                "lastName=" + lastName +
                '}';
    }
}
次のUsersRepositoryインタフェースを作成します。このインタフェースは、NosqlRepositoryインタフェースを拡張して、そのクラスの主キーのエンティティ・クラスとデータ型をパラメータ化された型としてNosqlRepositoryインタフェースに提供します。このNosqlRepositoryインタフェースは、データベースのデータの格納または取得に使用されるメソッドを備えています。
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);
}
SpringのCommandLineRunnerインタフェースを使用して、runメソッドを実装し、mainメソッドを持つアプリケーション・コードを表示できます。

ノート:

Spring Data Frameworkが提供する各種インタフェースのいずれかを実装することで、目的の要件に応じた機能をコーディングできます。Spring bootアプリケーションの設定の詳細は、「Spring Boot」を参照してください。
import com.oracle.nosql.spring.data.core.NosqlTemplate;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
 
/* The @SpringBootApplication annotation helps you to build an application using Spring Data Framework rapidly.*/
@SpringBootApplication
public class App implements CommandLineRunner {
 
    /* The annotation enables Spring Data Framework to look up the configuration file for a matching bean.*/
    @Autowired
    private UsersRepository repo;
 
    public static void main(String[] args) {
        ConfigurableApplicationContext ctx =
                SpringApplication.run(App.class, args);
        SpringApplication.exit(ctx, () -> 0);
        ctx.close();
        System.exit(0);
    }
 
    @Override
    public void run(String... args) throws Exception {
    }
}
Spring Dataアプリケーションを使用して表を作成すると、デフォルトのスキーマが自動的に作成され、主キー列(文字列、int、longまたはtimestamp型)とkv_json_というJSON列という2つの列が含まれます。

ノート:

表がすでに存在する場合は、生成されたスキーマに準拠する必要があります。

Users表のフィールドに索引を作成するには、NosqlTemplate.runTableRequest()を使用します。

Oracle NoSQL Databaseの接続詳細を指定するために、AbstractNosqlConfigurationクラスを拡張するAppConfigクラスを作成します。詳細は、「NoSQL接続の取得」を参照してください。

アプリケーションでは、AppConfigクラスのインスタンスにNosqlTemplate create (NosqlDbConfig nosqlDBConfig)メソッドを指定して、NosqlTemplateクラスをインスタンス化します。次に、NosqlTemplate.runTableRequest()メソッドを使用して表を変更します。NosqlTemplate.runTableRequest()メソッドで索引を作成するためのNoSQL文を指定します。

この例では、Users表のlastNameフィールドに索引を作成します。
import com.oracle.nosql.spring.data.core.NosqlTemplate;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
 
/* Create an Index on the lastName field of the Users Table. */
 
try {
    AppConfig config = new AppConfig();
    NosqlTemplate idx = NosqlTemplate.create(config.nosqlDbConfig());
    idx.runTableRequest("CREATE INDEX IF NOT EXISTS nameIdx ON Users(kv_json_.lastName AS STRING)");
    System.out.println("Index created successfully");
} catch (Exception e) {
    System.out.println("Exception creating index" + e);
}