2014年05月03日
川俣晶の縁側ソフトウェア技術雑記 total 7146 count

AzureのTableで前方一致検索を行う方法

Written By: 川俣 晶連絡先

「ただのメモだ」

「なんでメモするの?」

「AzureのTableでは前方一致検索ができるが、いくら探しても前方一致検索のためのAPIも演算子も出てこないからだ」

「うっそー」

アイデア §

「APIも演算子も無いのに、なんでできるの?」

「文字列比較の問題に還元するトリックを使えばいいわけだ」

「そんなに都合の良いことができるわけ?」

「つまり、"古代"よりも大きく"古代"+ '\uFFFF'よりも小さな文字列を探すと、古代進と古代守はヒットするが島大介と森雪はヒットしないわけだ」

「分かったぞ。この場合、比較は2回行われるんだ」

「そうだ」

「このテクニックにどんな意味があるの?」

「AzureのTableは特別扱いされるPartitionKeyとRowKeyをいかに使うかがキーになる。このうちPartitionKeyはパーティション分けにしか使えない」

「なんで?」

「バッチ操作でパーティションを跨ぐ操作を一括で実行できないからだ」

「じゃあRowKeyしか残らないじゃん」

「そうだ。しかし、RowKeyはユニークで無いと存在が許されない」

「もしかぶったら?」

「上書きされるだけだ」

「そうか。前方一致が許されると、同じIDを書き込みつつユニークを確保できるわけだね」

サンプルソース §

「取りあえず動いたものを載せているだけで、中身がいいかどうかは知らないぞ」

「えー」

        public ActionResult Index()

        {

            var account = Microsoft.WindowsAzure.Storage.CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString"));

            CloudTableClient tableClient = account.CreateCloudTableClient();

            var refer = tableClient.GetTableReference("SampleTable");

            refer.CreateIfNotExists();

            addSub(refer, "古代進");

            addSub(refer, "古代守");

            addSub(refer, "島大介");

            addSub(refer, "森雪");

            var svc = tableClient.GetTableServiceContext();

            string name_start = "古代";

            string name_end = name_start + '\uFFFF';

            var q = svc.CreateQuery<SampleData>("SampleTable").Where(c=>c.PartitionKey == "T" && (c.RowKey.CompareTo(name_start) >= 0 && c.RowKey.CompareTo(name_end) < 0));

            foreach (var item in q)

            {

              System.Diagnostics.Debug.WriteLine(item.RowKey);

            }

            return View();

        }

        private static void addSub(CloudTable refer, string name)

        {

            var d1 = new SampleData() { RowKey = name, PartitionKey = "T", ETag = Guid.NewGuid().ToString("N") };

            TableOperation op = TableOperation.InsertOrReplace(d1);

            refer.Execute(op);

        }

実行結果 §

古代進

古代守