C#
Azure
AzureStorage
BlobStorage

Azure BLOB Storageで前方一致検索を行う方法(を考慮したコンテナ名・ファイル名の設計)

こんな人に向けた記事

Azure BLOB Storageを使ってファイルを扱いたいけど検索って出来るの?やったことないので分かりやすいサンプルがあると助かるなーって思っていた人。

前提

C#er。Azure SDKがインストールされていること。

Storageの前方一致検索

C#メソッド例

using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Auth;
using Microsoft.WindowsAzure.Storage.Blob;
using System;

public static void GetList(string containerName, string prefix)
{
    var _accountName = "your_storage_account_name";
    var _accountKey = "your_storage_account_key";

    var externalStorageCredentials = new StorageCredentials(_accountName, _accountKey);
    var account = new CloudStorageAccount(externalStorageCredentials, true);
    var client = account.CreateCloudBlobClient();
    var container = client.GetContainerReference(containerName);
    container.CreateIfNotExists();

    var blobList = container.ListBlobs(prefix, true);
    foreach (var sourceBlob in blobList)
    {
        // このループ内で好きに処理してください。下記の例はコンソールにファイル名を出力しています。
        if (sourceBlob.GetType() == typeof(CloudBlockBlob))
        {
            CloudBlockBlob blob = (CloudBlockBlob)sourceBlob;
            var filename = blob.Name;

            Console.WriteLine(filename);
        }
    }
}

メソッド呼び出し例

var containerName = "container1";
var prefix = "folder1/folder2/samp";    //ファイル名の中間一致
//var prefix = "folder1/fol";           //フォルダ名の中間一致でもOK

GetList(containerName, prefix);

container1というコンテナに
folder1/folder2/sample1.txt
folder1/folder2/sample2.txt
というファイル名が存在していた場合、この2ファイルの名称が取得できます。

コンテナ名・ファイル名の設計

本題はこちらのつもりです。先に示した前方一致の検索がある前提を理解しないと、ここからの内容が役に立ちませんので先に実装方式を記載しました。

コンテナ名を決める

コンテナ名を決めるための理由は、大きく分けて以下があります。

  • 一括で消したい場合はコンテナ単位が速い

    • 一定期間で消す必要があるならコンテナ名は年月日で分けるとメリットがある
  • パーティションはコンテナ単位

    • 永続的に消さない場合、投入される(若しくは取り出したい)データがばらつくようなIDの場合にメリットがある。IoTであればGatewayId、DeviceId、SensorId等。

ということで、一番ダメな例は「SeonsorData」などの、上記2つのメリットのどちらも享受できない命名となります。

ファイル名を決める

ファイル名には/が使えますので子フォルダがあるように見えますが、実際は/も文字列として使えるだけのファイル名になります。
先の例で "folder1/folder2/sample1.txt" というファイル名を検索する場合に "folder1/folder2/samp" , "folder1/fol" のどちらでもこのファイルは検索されました。この挙動を踏まえてファイル名を決めます。

  • コンテナ名以外で優先される属性がある場合、その属性を利用優先の高い順に並べる

年月日/DeviceId/dataname
DeviceId/年月日時分秒/dataname

など、取得する場合に有利な方を選ぶと良いでしょう。
選択を誤った場合でもParallel.ForEachなどで取ってきてゴニョゴニョすればなんとかなるでしょう。とはいえ処理効率が高くなるように設計段階で考えておくに越したことはありません。
例えばDBも併用しつつ、DB使わなくてもそこそこ検索性能悪くないように作る努力をしましょう。

まずは試しましょう

サンプルコード書いて、入れたり出したりしつつ、実データがどう格納されたかをAzureポータルから覗いてみましょう。