データストアの使用ガイド

*このコンテンツは、ベータ版のAI(人工知能)を使用して翻訳されており、エラーが含まれている可能性があります。このページを英語で表示するには、 こちら をクリックしてください。

Studio またはライブサーバーで データストア にエンジン API を使用してアクセスし、利用することに加えて、グランュラルなアクセスとセキュリティ制御を持つ外部のスクリプトやツールから 標準 および 注文 のデータストアにアクセスし、利用するためのオープンクラウド API を使用できます。

使用法

以下の API を使用して、ワークフローの複数の領域を改善できます:

  • 顧客サポートポータル : データストアは、ユーザーインベントリのアイテムやスキルポイントなどの持続的なユーザー資源を保存するのに便利です。時々、これらのリソースを更新して顧客サポートに必要があります。スタジオを使用するか、エクスペリエンスに手動で参加するのではなく、カスタマーサポート客サポートエージェントがユーザーのインベントリの表示や変更、返品の発行などの顧客サポートリクエストを直接処理できるウェブアプリケーションを構築できます。

  • LiveOps ダッシュボード : APIを使用して、ライブ操作の効率を向上させるためにライブ操作ダッシュボードを構築できます。たとえば、イベントを事前にスケジュールし、データストアの構成データの一部として機能フラグの下に隠し、イベントの公開に際してフラグを切り替える時間を設定することができます。エクスペリエンスサーバーは、イベントを起動するためにフラグを読んでこの変更を検出できます。

  • 外部リーダーボード : RoblRoblox(ロブロックス) の外であなたの経験を促進するには、レースのリーダーボードのような情報をリアルタイムで引き出し、外部ウェブサイトに表示できます。ウェブサイトが定期的に HTTP を介して最新のデータをリクエストし、ウェブページを更新するために、注文したデータストアに読み込み専用アクセスを付与できます。

  • データ移行自動化 : データは、新機能を対応するためにデータスキームをアップグレードするなど、エクスペリエンスが進化するにつれて変更または更新される可能性があります。既存のユーザーデータを失うのを避けるために、ある時点でデータストアを古いスキームから新しいスキームに移行する必要があります。現在のデータストアからそれぞれのエントリを読み込み、データを新しいスキームにマップし、エントリを新しいデータストアに戻してデータ移行を自動化する外部スクリプトを書くことができます。

エンジン API との違い

オープンクラウド APIは DataStoreService に似ていますが、いくつかの重要な違いがあります:

  • ユニバースIDとデータストア名 : エンジンAPIとは異なり、オープンクラウドAPIは非状態であり、どこからでも来ることができるため、リクエストを送信するときには常に 宇宙ID 、エクスペリエンスの唯一の識別子、およびデータストア名 を提供する必要があります .宇宙ID を取得する方法について詳しくは、宇宙ID を参照してください。

  • 作成と更新の別の権限 : エンジン API は、呼び出し時に存在しない場合、新しいエントリを作成しますが、エントリの作成と更新のためのオープンクラウドメソッドは別々です。特定の状況では、別々の権限がより安全で柔軟になる可能性があります。たとえば、既存のユーザーのプロフィールを編集できる顧客サポートツールを作成できますが、新しいユーザーのプロフィールを作成できません。

  • データシリアル化 : すべてのオープンクラウドエンドポイントでは、ネットワーク輸送の前にすべてのデータをシリアル化する必要があります。シリアル化は、オブジェクトをストリングに変換することを意味します。デシリアライズは反対です (文字列をオブジェクトに変換する)。エンジン API は入力コンテンツを自動的にシリアル化およびデシリアライズしますが、オープンクラウドの場合、入力データを JSON で自所有で生成または解析する必要があります。

セキュリティ許可

データストアはしばしばユーザープロフィールや仮想通貨などの敏感な情報を保存します。セキュリティを維持するために、各オープンクラウド APIには、リストAPIの List Keys 権限など、APIキーに追加する必要がある対応する権限があります。必要な権限を追加しないと、API 呼び出しはエラーを返します。各操作に必要な特定の権限については、API 参照の 標準 および 注文済みデータストア を参照してください。

API キーを構成するとき 、特定のエクスペリエンス内の各データストアに読み込み、既読き込み、およびリストの権限など、細かな権限を設定できます。または、エクスペリエンス内のすべてのデータストアを読んだり書いたりするためのキーを与えることもできます。すべてのデータストアを露出するのではなく、ツールに必要なデータストアのサブセットへのアクセスを制限することもできます。これは、キーが漏洩した場合の影響を軽減します。

ビルドツール

選択した言語を使用して、データストア用のオープンクラウド API でツールを構築し、操作ニーズを満たすことができます。次の例では、標準のデータストアと順序付けられたデータストアを使用して Python で ユーザーインベントリサポートポータル を構築するプロセスを説明し、外部の持続的リーダーボードを使用して順序付けられたデータストアを使用します。

ユーザーインベントリサポートポータル

このセクションでは、Python でユーザーインベントリのサポートポータルを構築する具体的な例を提供し、ユーザーのインベントリのサブセットをリストして読み込み、編集し、その後エクスペリエンスのデータスト保管に戻すことができます。

この例では、フォロー中のことを想定します:

  • ユーザーインベントリを保存するデータストアの名前は Inventory です。

  • 各データエントリのデータスキーマは "userId": {"currency": number, "weapon": string, "level": number} です。キーは単に userId です。

  • Python スクリプトは、プレフィックスに基づいてユーザーのインベントリのサブセットをリストし、プロモーションのためにバーチャル通貨を 10 増やし、データを更新します。

高レベルでは、API キー権限を追加してから、スクリプトを追加して、Python アプリを構築できます。

データストアにAPIキー権限を追加

この例のために API キーを作成するときは、次の設定を行うことを確認してください:

  1. From the API システムの選択 menu in the アクセス権限 section, select ユニバースデータストア .

  2. (オプション) データストアの セクション で、特定のデータストア用の API 操作を選択する

    1. 特定のデータストア操作 トグルを有効にします。デフォルトで読み込む、5つのデータストアが自動的にロードされますが、 + データストアをリストに追加 ボタンを介して追加のデータストアを追加できます。
    2. データスト保管の名前の横にあるドロップダウン矢印を選択し、データストアにアクセスしてほしい API 操作を選択します。
  3. 全体のエクスペリエンスのための API 操作を選択します。

    1. クリックする 経験を選択して追加する ドロップダウンを選択し、経験を選択します。
    2. エクスペリエンス操作 で、ドロップダウン矢印をクリックし、APIに追加したい操作を選択します。この例では、 エントリを読むエントリを更新する 、および エントリのキーをリストする を、全体のエクスペリエンスに選択します。
  4. [セキュリティ] セクション で、CIDR 記述 を使用して IP アクセスをキーに明示的に設定し、その日付以降に自動的にキーの動作が停止するように、明示的な期限を設定します。この例では、最初にローカルテストを行う予定がある場合は、IP 制限を 0.0.0.0/0 に設定して、期限を 30日 に延長させることができます。

ユーザーインベントリサポートポータルのスクリプトを追加

例のアプリの必要な権限で API キーを作成した後、アプリ機能を実行するために JavaScript コードを追加する必要があります。The ファイルは、 、 、および 方法を定義する方法を示します。update_inventory.js ファイルは、定義されたメソッドを使用して、ユーザーのインベントリのサブセットをリストし、各ユーザーの仮想通貨を増やし、データを更新します。

dataStoresMethods.js

const fetch = require('node-fetch');
class DataStores {
constructor() {
this._baseUrl =
'https://apis.roblox.com/datastores/v1/universes/{universeId}';
this._apiKey = process.env.API_KEY;
this._universeId = 'UNIVERSE_ID';
this.ATTR_HDR = 'Roblox-entry-Attributes';
this.USER_ID_HDR = 'Roblox-entry-UserIds';
this._objectsUrl = `${this._baseUrl}${this._universeId}/standard-datastores/datastore/entries/entry`;
this._incrementUrl = `${this._objectsUrl}/increment`;
this._listObjectsUrl = `${this._baseUrl}${this._universeId}/standard-datastores/datastore/entries`;
}
async _getHeaders() {
return { 'x-api-key': this._apiKey };
}
async getEntry(datastore, objectKey, scope = null) {
const url = `${
this._objectsUrl
}?datastoreName=${datastore}&entryKey=${objectKey}&scope=${scope || ''}`;
const response = await fetch(url, { headers: await this._getHeaders() });
const data = await response.json();
return data;
}
async listEntries(datastore, scope = null, prefix = '', limit = 100) {
const url = `${this._listObjectsUrl}?datastoreName=${datastore}&scope=${scope}&prefix=${prefix}&limit=${limit}`;
const response = await fetch(url, { headers: await this._getHeaders() });
const data = await response.json();
return data;
}
async incrementEntry(datastore, objectKey, incrementBy, scope = null) {
const url = `${
this._incrementUrl
}?datastoreName=${datastore}&entryKey=${objectKey}&incrementBy=${incrementBy}&scope=${
scope || ''
}`;
const response = await fetch(url, {
method: 'POST',
headers: await this._getHeaders(),
});
const data = await response.json();
return data;
}
}
module.exports = DataStores;
updateInventory.js

const DataStores = require('./dataStoresMethods');
const dataStoresApi = new DataStores();
// Set up
const datastoreName = 'Inventory';
// List keys for a subset of users
dataStoresApi.listEntries(datastoreName).then((keys) => {
console.log(keys);
});
// Read inventory for each user
for (let x = 0; x < 5; x++) {
const updatedObjectKey = `User_${x + 1}`;
dataStoresApi.getEntry(datastoreName, updatedObjectKey).then((value) => {
console.log(
`${updatedObjectKey} has ${value.gems} gems in their inventory`
);
});
}
// Update the currency of each user by 10
for (let x = 0; x < 5; x++) {
const updatedObjectKey = `User_${x + 1}`;
dataStoresApi
.incrementEntry(datastoreName, updatedObjectKey, 10)
.then((value) => {
console.log(
`${updatedObjectKey} now has ${value.robux} robux in their inventory`
);
});
}

テストするには、API_KEY 環境変数を設定し、JavaScript ファイルを実行します:


export API_KEY=... \
node updateInventory.js

外部の永スコアボードリーダーボード

このセクションでは、Python で外部の永続リーダーボードを作成する具体的な例を歩き、注文のデータストアに保存されたユーザー情報をリストし、編集し、それから外部ウェブサイトに公開することでプロモーションできます。

この例では、フォロー中のことを想定します:

  • コードサンプルは、デモ目的のプリ定義リストのユーザー名を作成します。自分のアプリケーションの場合、エクスペリエンスの実際のユーザーのリストを使用する必要があります。

  • コードサンプルは、デモ目的でエクスペリエンスに参加する各ユーザーに 50 ポイント追加します。自分のアプリケーションの場合、経験の設計に基づいてルールを定義する必要があります。

高レベルでは、API キー権限を追加してから、スクリプトを追加して、Python アプリを構築できます。

注文されたデータストアに API キー許可を追加

例のアプリケーションは、機能を達成するために 4つのメソッドが必要です: List , Create , UpdateIncrement , それで、次のAPIキー権限を追加する必要があります:

  • 読む 方法のために list メソッド。
  • 書く for Create , Update , そして Increment メソッド。

この例のために API キーを作成するときは、次の操作を行う必要があります:When creating an API Key for this example, make sure you perform the following operations:

  1. From the API システムの選択 menu in the アクセス権限 section, select 順序付けられたデータストア .

  2. ターゲットエクスペリエンスで注文されたデータストアの読み込みと書き込みの権限を API 操作に追加する。

    1. クリックして 経験を選択して追加する ドロップダウンを選択し、ターゲットの経験を選択します。
    2. エクスペリエンス操作 で、ドロップダウンを拡張して 読む書く 操作を選択します。
  3. [セキュリティ] セクション で、CIDR 記述 を使用して IP アクセスをキーに明示的に設定し、その日付以降に自動的にキーの動作が停止するように、明示的な期限を設定します。この例では、最初にローカルテストを行う予定がある場合は、IP 制限を 0.0.0.0/0 に設定して、期限を 30日 に延長させることができます。

リーダーボード用のスクリプトを追加

例のアプリの必要な権限で API キーを作成した後、アプリ機能を実行するために JavaScript コードを追加する必要があります。

The ファイルは、 、 、 、そして 方法を定義する方法を示します。 ファイルは、定義されたメソッドを使用して、順序のついたデータストアにユーザーのエントリを作成し、スコアを表示し、勝利ユーザーのスコアを増加し、リーダーボードを更新します。leaderboard.js ファイルは、宇宙ID、APIドメイン、および API キーを構成するための config.json ファイルもインポートします。

ordered_data_stores.js

const axios = require('axios');
const fs = require('fs');
class DataStores {
constructor(configFile) {
this._config = JSON.parse(fs.readFileSync(configFile, 'utf-8'));
}
_H() {
return {
'x-api-key': this._config.api_key,
'Content-Type': 'application/json',
};
}
async list(
datastore,
scope,
pageSize = 10,
orderBy = '',
filter = '',
exclusiveStartKey = ''
) {
const url = `${this._config.api_key_url}universes/${this._config.universe_id}/orderedDataStores/${datastore}/scopes/${scope}/entries`;
const response = await axios.get(url, {
headers: this._H(),
params: {
max_page_size: pageSize,
order_by: orderBy,
filter: filter,
page_token: exclusiveStartKey,
},
});
return response.data;
}
async create(datastore, scope, entry, data) {
const url = `${this._config.api_key_url}universes/${this._config.universe_id}/orderedDataStores/${datastore}/scopes/${scope}/entries`;
const payload = JSON.stringify({ value: 11 });
const response = await axios.post(url, payload, {
headers: this._H(),
params: { id: entry },
});
return response.data;
}
async increment(datastore, scope, entry, incrementBy) {
const url = `${this._config.api_key_url}universes/${this._config.universe_id}/orderedDataStores/${datastore}/scopes/${scope}/entries/${entry}:increment`;
const payload = JSON.stringify({ amount: incrementBy });
const response = await axios.post(url, payload, { headers: this._H() });
return response.data;
}
}
leaderboard.js

const leaderboardEndpoints = require('./ordered_data_stores');
const datastores = new leaderboardEndpoints.DataStores('config.json');
// Variables
const orderedDataStore = 'PlayerScores';
const scope = 'global';
const entryNames = ['Ragdoll', 'Balinese', 'Tabby', 'Siamese'];
// Create an entry and give each new player 50 points for joining the game
entryNames.forEach(async (name) => {
await datastores.create(orderedDataStore, scope, name, 50);
});
// Display the players' scores
datastores.list(orderedDataStore, scope).then((playerScores) => {
console.log(playerScores);
});
// Increment the first player's score for winning the game
datastores.increment(orderedDataStore, scope, entryNames[0], 100);
// Increment all the players' scores for participating in the game
entryNames.forEach(async (name) => {
await datastores.increment(orderedDataStore, scope, name, 10);
});
// Display the updated leaderboard
datastores.list(orderedDataStore, scope).then((updatedPlayerScores) => {
console.log(updatedPlayerScores);
});
構成

{
"universe_id": "",
"api_key_url": "https://apis.roblox.com/datastores/ordered-v1/",
"api_key": ""
}

テストするには、API_KEY環境変数を設定し、leaderboard.jsファイルを実行します:


export API_KEY=... \
node leaderboard.js

テストを完了した後、リーダーボードを Roblox 以外のウェブサイトに公開または埋め込んで、より多くのリーチを得ることができます。