Salesforce Developer Editionの限界
(4)Salesforseでリアルタイム監視で説明したが、Salesforce Developer Editionは、利用可能なデータストレージが5MByteしかない。
はじめ、電流値のロギングを10秒周期でアップロードしていたが、1日半で制限に引っかかり、アップロード不能になってしまった。
最も手っ取り早い対策方法は、アップロード周期を長めにとることである。
しかし、この制限を意識せずに利用する方法が存在する。
それは、BigObjectを活用することである。
BigObjectとは?
主に、履歴やログを残すのに用いられるオブジェクトである。
Developer Editionでは100万レコードまで保持することが可能である。
BigObjectが通常のオブジェクトと異なるところは、
・ レポートやダッシュボードなど通常の機能で使用できない。
・ 通常のカスタムオブジェクトはAPIアクセス名に「__c」がついたが、BigObjectは「__b」
・ リレーショナルデータベースでなく分散型データベース
・ 非トランザクションデータベース
詳細は以下を参照
【参照】
Salesforce および Lightning プラットフォームのオブジェクトリファレンス
どう活用できるの?
まず、手始めに、作成したカスタムオブジェクトと同等の項目定義をもつBigObjectを作成しておき、容量オーバーになる前にカスタムオブジェクトのデータをBigObjectにバックアップしてから削除することができる。
BigObjectに格納しても標準のレポート機能で使用できないのでグラフ表示できない!と思われるかもしれないが、ちょっと頑張れば、この問題をクリアする方法がある。
自分で作成するVisualforceページからはBigObjectにアクセス可能である。
BigObjectの作成
「設定」-「管理」-「データ」-「BigObject」を選択する。
「New」ボタンをクリックする。
表示ラベル・オブジェクト名を指定して「保存」する。
カスタム項目&リレーションで「新規」をクリック。
データ型を選択して「次へ」
この辺はカスタムオブジェクト作成時と同じである。
カスタムオブジェクトと同様に項目を作成すること。
ただし、数式項目は作成できないので注意する。
カスタムオブジェクトからBigObjectへのデータバックアップ
ここでは、開発者コンソールを利用して作業を行う。
開発者コンソールは、「設定」同様、画面右上のギアボタンのメニューから起動できる。
「開発者コンソール」を選択すると、別ウィンドウで開発者コンソールが起動する。
開発者コンソールでは、SOQL (Salesforceで使用するSQL)を実行できる。
画面下のパネルの「Query Editor」にSOQLを入力し、一番下のExecuteをクリックする。すると、真ん中のパネルに実行結果が表示される。
これで、現在保持しているデータを確認できる。
では、データをカスタムオブジェクトから引き出して、BigObjectに格納するにはどうしたらよいか?
これは、普通にSOQLを発行するだけでは不可能である。
これには、Apexを使用する。
上部メニューから「Debug」-「Open Execute Anonymous Window」をクリック。
Enter Apex Codeウィンドウが起動するので、実行したいApexコードを入力する。
サンプルコード
List <GeneratorLog__c> lst =
[SELECT Id,Name,Current__c,Voltage__c,Temperature__c FROM GeneratorLog__c WHERE MeasDate__c= TODAY AND hour__c=12] ;
if (lst.size() > 0 ) {
for(GeneratorLog__c data : lst)
{
GeneratorLogStack__b entity = new GeneratorLogStack__b(
No__c = data.Name,
Date__c = data.Name,
Current__c = data.Current__c,
Voltage__c = data.Voltage__c,
Temperature__c = data.Temperature__c
);
Database.insertImmediate(entity);
}
delete lst;
system.debug('★' + lst.size()+ '件 削除しました★');
} else {
system.debug('★該当データなし★');
}
入力したソースは、Executeボタンクリックで実行される。
ただし、一回の実行時間に制限がある。(10秒くらい)
大量にデータをコピー・削除しようとすると、途中で切られてしまうので、Where条件でデータを分割しながらデータ移行するとよい。
Visualforceページの作成
バックアップしたデータも、やはりグラフ表示できると嬉しい。
これにはVisualforceページを使用する。
Visualforceページの作成は以下の手順で行う。
「設定」-「プラットフォームツール」-「カスタムコード」-「Visualforceページ」を選択。
「新規」ボタンをクリック。
表示ラベルと名前を入力する。
デフォルトで数行コードが書かれており、そのまま保存してプレビューすると、以下のページが表示されるようになる。
ここで、「私の個人情報」-「高度なユーザの詳細」で、「開発モード」のチェックがONになっていると、ページ左下に「X」ボタンが出現する。
これをクリックすると、コードエディタが下部に表示され、出力を確認しながらコードを書けるようになっている。
次に、コードの実装に移るが、Visualforceの実装の前に、VisualforceページコントローラをApexで作成する必要がある。
Apexクラスの作成は、
「設定」-「プラットフォームツール」-「カスタムコード」-「Apexクラス」を選択。「新規」ボタンを押し、ここでは「ChartController」という名前でクラスを作成する。
public class ChartController {
static String searchText;
public String getSearchText() {
return searchText;
}
public void setSearchText(String s) {
searchText = s;
}
List<Data> results;
// Return a list of data points for a chart
public List<Data> getData() {
return ChartController.getChartData();
}
// Make the chart data available via JavaScript remoting
@RemoteAction
public static List<Data> getRemoteData()
{
return ChartController.getChartData();
}
public static Decimal Average(List<Decimal> numlist)
{
Decimal ret=0;
Decimal sum=0;
for(Decimal d : numlist)
{
sum += d;
}
if(numlist.size()>0)
{
ret = sum/numlist.size();
}
return ret;
}
public List<Data> getResults() {
return results;
}
public PageReference doSearch() {
results = getChartData();
return null;
}
// The actual chart data; needs to be static to be
// called by a @RemoteAction method
public static List<Data> getChartData() {
List<Data> data = new List<Data>();
List<List<Decimal>> currentPH = new List<List<Decimal>>();
List<List<Decimal>> voltagePH = new List<List<Decimal>>();
List<List<Decimal>> tempPH = new List<List<Decimal>>();
for(Integer i=0;i<18;i++)
{
currentPH.add(new List<Decimal>());
voltagePH.add(new List<Decimal>());
tempPH.add(new List<Decimal>());
}
Date d = Date.newInstance(Integer.valueOf(searchText.left(4)), Integer.valueOf(searchText.mid(5, 2)), Integer.valueOf(searchText.mid(8,2)));
String dateP = String.valueOf(d.addDays(-1));
String dateL = String.valueOf(d.addDays(1));
List<GeneratorLogStack__b> lst = [SELECT No__c, Date__c, Current__c, Voltage__c, Temperature__c FROM GeneratorLogStack__b WHERE No__c < :dateL AND No__c > :dateP];
for (Integer i=0;i<lst.size();i++)
{
GeneratorLogStack__b entity=lst[i];
Integer hour = Integer.valueOf(entity.No__c.mid(11,2));
currentPH[hour].add(entity.Current__c);
voltagePH[hour].add(entity.Voltage__c);
tempPH[hour].add(entity.Temperature__c);
}
for(Integer i=7;i<18;i++)
{
data.add(new Data(i.format(), Average(currentPH[i]), Average(voltagePH[i]), Average(tempPH[i])));
}
return data;
}
// Wrapper class
public class Data {
public String name { get; set; }
public Decimal data1 { get; set; }
public Decimal data2 { get; set; }
public Decimal data3 { get; set; }
public Data(String name, Decimal data1, Decimal data2, Decimal data3) {
this.name = name;
this.data1 = data1;
this.data2 = data2;
this.data3 = data3;
}
}
}
【参照】
Visualforce Charting を使用した複雑なグラフの作成
Apexクラスを保存したら、再びVisualforceの編集を行う。
<apex:page controller="ChartController">
<apex:form >
<apex:pageBlock mode="edit" id="block">
<apex:pageBlockSection >
<apex:pageBlockSectionItem >
<apex:outputLabel for="searchText">Search Date</apex:outputLabel>
<apex:panelGroup >
<apex:inputText id="searchText" value="{!searchText}"/>
<apex:commandButton value="Go" action="{!doSearch}" rerender="block" status="status"/>
</apex:panelGroup>
</apex:pageBlockSectionItem>
</apex:pageBlockSection>
<apex:actionStatus id="status" startText="requesting..."/>
<apex:pageBlockSection title="Results" id="results" >
<apex:chart height="400" width="700" data="{!results}">
<apex:legend position="right"/>
<apex:axis type="Numeric" position="left" fields="data1"
title="Currenct(A)" grid="true"/>
<apex:axis type="Category" position="bottom" fields="name"
title="Hour">
<apex:chartLabel rotate="315"/>
</apex:axis>
<apex:lineSeries title="{!searchText}" axis="left" xField="name" yField="data1"
fill="true" markerType="cross" markerSize="4" markerFill="#FF0000"/>
</apex:chart>
<apex:chart height="400" width="700" data="{!results}">
<apex:legend position="right"/>
<apex:axis type="Numeric" position="left" fields="data2"
title="Voltage(V)"/>
<apex:axis type="Category" position="bottom" fields="name"
title="Hour">
<apex:chartLabel rotate="315"/>
</apex:axis>
<apex:lineSeries title="{!searchText}" axis="left" xField="name" yField="data2"
markerType="circle" markerSize="4" markerFill="#8E35EF"/>
</apex:chart>
</apex:pageBlockSection>
</apex:pageBlock>
</apex:form>
</apex:page>
このコードを保存して実行すると、以下のような画面になる。
テキストボックスに年月日を「yyyy-MM-dd」形式で指定すると、該当する日付の電流/電圧グラフが表示される。
あとは、このVisualforceページ用のタブを作成するだけである。
「設定」-「プラットフォームツール」-「ユーザインターフェース」-「タブ」を開き、Visualforceページタブを新規作成する。
作成したタブを、任意のアプリケーションに追加すると画面から簡単にアクセスできるようになる。
もう少しUIを工夫すれば、標準レポートを使用せず、最初からすべてのデータをBigObjectに投入し、Visualforceページで監視することも可能だ。