atelier:mitsuba

i love UI/UX, Blend, XAML, Behavior, P5, oF, Web, Tangible Bits and Physical computing. なにかあればお気軽にご連絡ください。atelier@c-mitsuba.com

namelessをBlob Index Tags対応して、アオで集めたギャラリーを作った。

ちまちまと運用してるphoto Portfolioのnameless。

c-mitsuba.hatenablog.com

c-mitsuba.hatenablog.com

もうすぐ作って1周年らしい。
そろそろネームカードも作りたいと思いつつ作ってないな。。


で、このnameless、前からちょくちょく言ってるけどDBを完全に持たずにBlobだけで写真管理してる。
それでもって昨日ようやくBlob Index TagsがGAされたので、サクッと組み込んでみた。

作ったのは、こんな風にアオを基調としたギャラリー。
f:id:c-mitsuba:20210619053005p:plain




Blob Index Tagsってのは、Metadataとは別にDictionaryで定義できる横断検索用のキーワード。
docs.microsoft.com

まずはTagsの書き込み。
今回はTagsにその写真のメインカラーっぽいものを入れていく。

管理画面のコードの一部はこんなかんじ。

                var now =
                    $"{DateTime.Now.Year}:{DateTime.Now.Month:D2}:{DateTime.Now.Day:D2} {DateTime.Now.Hour}:{DateTime.Now.Minute:D2}:{DateTime.Now.Second:D2}";

                var blobClient = blobContainerClient.GetBlobClient(id);
                var propertiesAsync = await blobClient.GetPropertiesAsync();
                var metadata = new Metadata(propertiesAsync.Value.Metadata);
                var tagsAsync = await blobClient.GetTagsAsync();
                var tags = new Tag(tagsAsync.Value.Tags);

                return View(new GraphViewModel
                {
                    Photo = id,
                    Camera = metadata.Camera,
                    Sentence = metadata.Sentence,
                    Title = metadata.Title,
                    IsHidden = metadata.IsHidden,
                    ShootingDate = string.IsNullOrEmpty(metadata.ShootingDate) ? now : metadata.ShootingDate,
                    Color = tags.Color == "None" ? "" : tags.Color
                });

で、Tagsっぽいコードはココ。

                var tagsAsync = await blobClient.GetTagsAsync();
                var tags = new Tag(tagsAsync.Value.Tags);

new Tag()はnew Metadata()と完全に同じ仕様でDictionaryを定義したクラスに変換するパーサー。
コードの扱いはMetadataまわりのコードを使い回せるのがいい感じ(まぁ中身が Dictionaryで同じ型だからそりゃそう。)

かんたん。


次にTagsを取ってくるほうのコード。

            var blobContainerClient = Blob.GetBlobContainerClient(BlobType.Original);

            var blobList = await blobContainerClient.GetBlobsAsync(BlobTraits.Metadata | BlobTraits.Tags)
                                                    .Select(o => new { blob = o, meta = new Metadata(o.Metadata), tag = new Tag(o.Tags) })
                                                    .Where(t => !t.meta.IsHidden && t.tag.Color == TagColors.Blue.ToString())
                                                    .OrderByDescending(t => t.meta.ShootingDate).Select(t => t.blob)
                                                    .ToListAsync();

            var model = new IndexViewModel { BlobItems = blobList };
            return View("Index", model);

まず、もともとGetBlobAsyncでMetadataだけ取ってたところに、合わせてTagsも取るように追記。

await blobContainerClient.GetBlobsAsync(BlobTraits.Metadata | BlobTraits.Tags)

あとはパースして、Whereで絞り込んでおしまい。

.Where(t => !t.meta.IsHidden && t.tag.Color == TagColors.Blue.ToString())


で、出来上がったのがこんなページ。


blue - nameless
  gallery - nameless

mono - nameless
  gallery - nameless

いろんな写真が雑多に並んでるのもカラフルで楽しいけど、同じ色味の写真が並んでるのもなんかギャラリー感があっていいな。




そういや、先日公開されたVS 2022 Enterprise Preview 1 で書いてみてるけど、結構快適でいいかんじ。



追記+++++
上の絞り込みだとMetadataと使い方が一緒で、どうやら使い方が違うっぽい。
どうやら、BlobServiceClientに対して、FindBlobByTagsAsync()するのが正しそう。
確かにBlobContainerClientだと横断的に検索できないよなぁ。。。
今度正しいコードに書き直してみよう。