オーストラリア料理

こんにちは。開発担当のマットです。

今、日本に住んでいますけれども、オーストラリア生まれ育ちで、このあいだ、家族と会うためにオーストラリアに一時的に帰国させていただきました〜 (行きも帰りも2週間の隔離をやりましたので、ご安心くださいw)

オーストラリアに行っている間、日本で中々食べられないオーストラリア料理や調味料を食べれて、この記事でそれらを日本人の皆様に紹介したいと思います。

ミント・ゼリー

英名: Mint Jelly

Author: Jeremy Keith from Brighton & Hove, United Kingdom

ミント・ゼリーはその名の通り、ミントから作られるゼリーです。
実はミントよりも、リンゴ酢と砂糖がメインな具材ですけれども、ミントをちょっと入れるだけでミントの味が勝ちますね。
デザートではなく、ラム肉や焼き野菜の上にちょっと乗せる調味料です。

実は一年前、親戚の畑の一部がミントにはびこっていましたので、採りに行って自分で作ろうとしました。家中がミントの匂いに覆われ、最終的に酸っぱくなりすぎて、あまり美味しくないものをできてしまいました。
でも、美味しいミント・ゼリーを食べたら、抜群に美味いです。

日本人も絶対好きな味だと思います。

ミート・パイ

英名: Meat Pie

Author: Finbar.concaig

毎日の朝食に、ミート・パイを食べるオーストラリア人は少なくないと思います。

オーストラリアのパン屋さんに行くと、食パンの次に多いのはパイです。
多くの味があります。ビーフのパイは代表的ですが、カレー・チキン、ステーキ・マッシュルームなど、多くの種類はあります。

一度、贅沢をして、「和牛ステーキ・ブルーチーズ・マッシュルーム」のパイを食べたことがあります。
最高に美味しかったです。

オーストラリアですので、必ずケッチャプをたくさん掛けます。
ちなみに、オーストラリアで「ケッチャプ」の言葉は決して言いません。「トマト・ソース」と呼びます。

牛肉コロッケなどが好きな方なら、ミート・パイを気に入ると思います。

パヴロヴァ

英名: Pavlova

Author: William Brawley

メレンゲのケーキを焼いて、その上に生クリームとフルーツを乗せるデザートです。
メレンゲの味付けもできますし、フルーツを好きなものにできますので、各家族に「ウチの味のパヴロヴァ」ってありますね。僕はレモンメレンゲにキウィフルーツが好きです。

もともとロシアのバレーダンサーの家庭のレシピだったそうですが、オーストラリアとニュージーランドで流行りまして、そこからオージー・ニュージーのデザートを代表するヒットになりました。

日本でも流行ったら大人気になると思います。

ベジマイト

英名: Vegemite

Author: Tristanb

僕の心の中でベジマイトは日本の納豆の役割を果たしています。
日本人の中でも納豆の好き嫌いはありますが、外国人に「納豆を食べれますか?」と聞くことが多い。
ベジマイトも同様。オーストラリア人の中にも好き嫌いは多いけど、「オーストラリア人しか食べられないでしょう…」のイメージが付いている物ですね。

味自体は苦いです。
イースト菌と野菜のエキスから作られているスプレッド(パンに塗るもの)です。

青汁とか、濃い味噌の味が好きな方なら、日本人の中でも好きな人はいるかと思いますが、おそらく99%の日本人はベジマイトを食べたら「嫌い」というと思いますw

まとめ

他にもたくさんありますが、この記事を書くと、お腹がペコペコになってしまいました。
冷蔵庫にあるベジマイトを久しぶりに出して、サンドイッチでも食べようかな。

ソフトウェアの開発担当として、毎日コツコツ、近くにいるエンジニアさん達からも、インターネットの方々からも、色々なことを学んで、自分の力を磨き上げることは仕事です。
私生活にでも、食生活にでも、近くにいる人と外国からも、良い知識を学んで、新しい料理を作ってみたりとかして、日常を少し豊かにすることはいいかもしれませんね。

[Solr] Stored フィールドと DocValued フィールド

Solr の検索処理の要は転置インデックスです。転置インデックスは概念的には以下のようなデータ構造になっています。

キーワード文書ID
製品文書1,文書3,文書4
部品文書2,文書5,文書6

転置インデックスを使うことで、「部品」を含む文書の文書IDが2と5と6である、といったことを効率良く調べることができます。ただし、利用する機能(ソート、ファセット、ハイライティング)によっては特定のドキュメントに含まれるキーワードを調べるためのデータ構造があると効率が良いことがあります。それが DocValues です。

DocValues は以下のようなデータ構造です。

フィールド名文書ID→フィールド値のマップ
name{“文書1″:”製品1”, “文書2″:”部品1”, “文書3″:”製品2”, “文書4″:”製品3”, “文書5″:”部品2”, “文書6″:”部品3”}
price{“文書1”:1000, “文書2”:100, “文書3”:2000, “文書4”:3000, “文書5”:200, “文書6”:300}

すべての文書(あるいは特定の文書セット)における特定のフィールド値をまとめて取得できるデータ構造となっています。

たとえば name:部品 という検索で price フィールドを対象にファセットを作るとします。
この場合、転置インデックスによって「部品」を含む文書IDが2,5,6であることが分かり、それぞれの price フィールドの値が 100,200,300 であることが効率よく調べられます。
DocValues を使うには、対象としたいフィールドの定義で docValues=”true” を指定します。

文書IDからフィールド値を調べるためのデータとしては、フィールド定義で stored=”true” を指定することで格納されたフィールド値も利用できます。stored のデータ構造は以下のようなものです。

文書IDフィールド名→フィールド値のマップ
文書1{“name”:”製品1″, “price”:1000}
文書2{“name”:”部品1″, “price”:100}
文書3{“name”:”製品2″, “price”:2000}
文書4{“name”:”製品3″, “price”:3000}
文書5{“name”:”部品2″, “price”:200}
文書6{“name”:”部品3″, “price”:300}

特定の文書IDに紐づくすべてのフィールド値を一括して取得できるデータ構造となっています。

stored=”true” かつ docValues=”false” なフィールドに対してソート、ファセット、ハイライティングといった処理をするために、DocValues に近いデータ構造が FieldCache として Java ヒープ上に作られます。FieldCache は実行時に作られるもので、キャッシュデータが揃うまでに時間が掛かるとかJavaのヒープ使用量が大きくなるとかいった欠点があります。

それに対して DocValues はインデックス作成時に同時に作られます。OSのファイルキャッシュに乗るため、実行時のコストを小さくすることができます。

一年後も崩れにくい服のたたみ方

数ヶ月着ないうちにタンスの中でグチャッとなったシワシワのTシャツ、たまに見かけることないですか?
このたたみ方を習得すると、1年後もタンスの中で畳んだときの姿のままで保存することができます。

今回は、Tシャツ、長ズボン、パーカーのたたみ方をご紹介します。

一年後も崩れにくい、Tシャツのたたみ方

① シワを伸ばして広げておいたら、上下から中心に合わせてたたみます
② 次に左右から中心に合わせてたたみます
③ ここがポイント!裾側に襟側を入れ込む!
④ 完成!
フリスビーのように壁に投げても崩れません。

一年後も崩れにくい、長ズボンのたたみ方

① 背面が下に来るようにおいたら、上下半分にたたみます
② お尻の飛び出た部分を折り込んでまっすぐになるようにします

③ 半分にたたみます
④ ウエスト側を3分の1を目安に内側へたたみます

⑤ ここがポイント!ウエスト側に反対側を入れ込む!
⑥ 完成!

ズボンも壁に投げても崩れませんでした。

一年後も崩れにくい、パーカーのたたみ方

① シワを伸ばして広げておいたら片側から中心に合わせてたたみ、そでにもシワが寄らないように裾に向かって広げてたたみます
② 反対側も同様にたたんだら、フードの形を整えます

③ 4分の1を目安に、裾側を中心へ向かってたたみます
④ 裾側の四角(黄色)のサイズになるようフード側もたたみます

⑤ ここがポイント!(3回目)裾側にフード側を入れ込む!
⑥ 完成!

きれいに畳む事ができました。ぜひ、お試しください。

[Solr] Cross Collection Join と Range Hash Query

Solr リファレンスの Cross Collection Join の項に以下の説明があります。

If the local index is sharded according to the join key field, the cross collection join can leverage a secondary query parser called the “hash_range” query parser. The hash_range query parser is responsible for returning only the documents that hash to a given range of values. This allows the CrossCollectionQuery to query the remote Solr collection and return only the join keys that would match a specific shard in the local Solr collection. This has the benefit of making sure that network traffic doesn’t increase as the number of shards increases and allows for much greater scalability.

https://solr.apache.org/guide/8_9/other-parsers.html#cross-collection-join

意訳

ローカルインデックスが join key フィールドでシャードに分けられている場合、Cross Collection Join はHash Range クエリパーザという補助的なクエリパーザを利用できます。Hash Range クエリパーザは、そのハッシュが指定された範囲に収まるドキュメントだけを返す役目を持っています。これにより、CrossCollectionQuery はリモートの Solr コレクションにクエリを投げたときにローカル側のコレクションの特定のシャードにだけマッチする join key を受け取ることができます。この機能にはシャード数が増加してもネットワークトラフィックが増えないという利点があり、非常に優れたスケーラビリティを実現します。

この動作を確認してみます。前回同様

ローカルインデックス: http://localhost:8983/solr/collection1
リモートインデックス: http://localhost:7574/solr/collection2

です。それぞれ以下のようなデータが入っています。

$ curl -s 'http://localhost:8983/solr/collection1/select?q.op=AND&q=*%3A*&rows=5'
{
  "responseHeader":{
    "zkConnected":true,
    "status":0,
    "QTime":4,
    "params":{
      "q":"*:*",
      "q.op":"AND",
      "rows":"5"}},
  "response":{"numFound":9238,"start":0,"maxScore":1.0,"numFoundExact":true,"docs":[
      {
        "id":"名所・旧跡!4548",
        "type_str":"名所・旧跡",
        "name_str":"高砂神社",
        "_version_":1706788558129332224},
      {
        "id":"名所・旧跡!4549",
        "type_str":"名所・旧跡",
        "name_str":"高崎神社",
        "_version_":1706788558131429376},
      {
        "id":"名所・旧跡!4550",
        "type_str":"名所・旧跡",
        "name_str":"大阪護国神社",
        "_version_":1706788558131429377},
      {
        "id":"名所・旧跡!4551",
        "type_str":"名所・旧跡",
        "name_str":"極楽寺",
        "_version_":1706788558131429378},
      {
        "id":"名所・旧跡!4552",
        "type_str":"名所・旧跡",
        "name_str":"あびこ観音",
        "_version_":1706788558131429379}]
  }}
$ curl -s 'http://localhost:7574/solr/collection2/select?q.op=AND&q=*%3A*&rows=5'
{
  "responseHeader":{
    "zkConnected":true,
    "status":0,
    "QTime":5,
    "params":{
      "q":"*:*",
      "q.op":"AND",
      "rows":"5"}},
  "response":{"numFound":9238,"start":0,"maxScore":1.0,"numFoundExact":true,"docs":[
      {
        "id":"名所・旧跡!4548",
        "area_str":"住之江区",
        "address_str":"住之江区北島3-14-12",
        "address_p":"34.6003421111111,135.477833138888",
        "_version_":1706808733657464832},
      {
        "id":"名所・旧跡!4549",
        "area_str":"住之江区",
        "address_str":"住之江区南加賀屋4-15-3",
        "address_p":"34.6014560555555,135.474182833333",
        "_version_":1706808733658513408},
      {
        "id":"名所・旧跡!4550",
        "area_str":"住之江区",
        "address_str":"住之江区南加賀屋1-1-77",
        "address_p":"34.6102029722222,135.473905944444",
        "_version_":1706808733659561984},
      {
        "id":"名所・旧跡!4551",
        "area_str":"住吉区",
        "address_str":"住吉区遠里小野5丁目",
        "address_p":"34.6003890555555,135.495708055555",
        "_version_":1706808733659561985},
      {
        "id":"名所・旧跡!4552",
        "area_str":"住吉区",
        "address_str":"住吉区我孫子4丁目",
        "address_p":"34.5989438333333,135.508442333333",
        "_version_":1706808733659561986}]
  }}

idフィールドが CompositId になっており、type_str の値でシャーディングされます。
シャードが4つの場合、以下のような配置となっています。

$ curl -s 'http://localhost:8983/solr/collection1/select?facet.field=type_str&facet=on&q=*:*&rows=0&shards=shard1'|jq .facet_counts.facet_fields.type_str
[
  "名所・旧跡",
  561,
  "環境・リサイクル",
  53
]
$ curl -s 'http://localhost:8983/solr/collection1/select?facet.field=type_str&facet=on&q=*:*&rows=0&shards=shard2'|jq .facet_counts.facet_fields.type_str
[
  "駐車場・駐輪場",
  1049,
  "学校・保育所",
  1045,
  "医療・福祉",
  840,
  "会館・ホール",
  642,
  "官公庁",
  301,
  "その他",
  141
]
$ curl -s 'http://localhost:8983/solr/collection1/select?facet.field=type_str&facet=on&q=*:*&rows=0&shards=shard3'|jq .facet_counts.facet_fields.type_str
[
  "駅・バス停",
  2574,
  "警察・消防",
  330,
  "文化・観光",
  290
]
$ curl -s 'http://localhost:8983/solr/collection1/select?facet.field=type_str&facet=on&q=*:*&rows=0&shards=shard4'|jq .facet_counts.facet_fields.type_str
[
  "公園・スポーツ",
  1090,
  "公衆トイレ",
  322
]

それぞれのシャードのハッシュの値の範囲は以下の通りです。

$ curl -s 'http://localhost:8983/solr/admin/collections?action=COLSTATUS&collection=collection1&coreInfo=true' |jq '.collection1.shards | {(keys[0]):[.[].range][0],(keys[1]):[.[].range][1],(keys[2]):[.[].range][2],(keys[3]):[.[].range][3]}'
{
  "shard1": "80000000-bfffffff",
  "shard2": "c0000000-ffffffff",
  "shard3": "0-3fffffff",
  "shard4": "40000000-7fffffff"
}

ここで type_str:文化・観光 で area_type:中央区 のデータを Cross Collection Join で検索してみます。

type_str:文化・観光 {!join ttl=1 routed=\"true\" method=\"crossCollection\" fromIndex=\"collection2\" from=\"id\" to=\"id\" solrUrl=\"http://localhost:7574/solr\" v=\"area_str:中央区\"}

routed=true を指定して、Range Hash クエリを有効にしています。
この検索におけるリモートインデックス側(7574のSolr)のログを確認すると、以下のような検索クエリが来ていることが分かります。

2021-07-31 16:52:56.699 INFO  (qtp1620529408-898) [c:collection2 s:shard1 r:core_node3 x:collection2_shard1_replica_n1] o.a.s.c.S.Request [collection2_shard1_replica_n1]  webapp=/solr path=/stream params={indent=off&expr=unique(search(collection2,q%3D"area_str:中央区",fq%3D"{!hash_range+f%3Did+l%3D0+u%3D1073741823}",fl%3Did,sort%3D"id+asc",qt%3D"/export",method%3DcrossCollection),over%3Did)&wt=javabin&version=2.2} status=0 QTime=0

Hash Range を指定しているのは以下の部分です。

{!hash_range f:id l:0 u:1073741823}

idフィールドのハッシュ値の下限が0,上限が1073741823と指定されています。1073741823を16進数に直すと3FFFFFFFです。type_str:文化・観光 が属する shard3 にマッチするものだけが要求されていることが分かります。

iOSでアプリを固定する方法

設定自体は割と簡単で下記の手順で行えます。

アクセシビリティ

手順1.アクセスガイドの設定を有効にする
設定>アクセシビリティ>アクセスガイドを有効にしてパスコードを設定する

手順2.アクセスガイドを起動する
固定したいアプリを起動してアクセスガイドの設定の下に書いてあった「ホームボタン」か「トップボタン」を3回押して何も選択せず開始

アプリの固定は上記の手順2で完了です。解除する場合は同じように3回押してパスコードを入力後終了すれば戻ります。

利用シーンとしては業務用アプリとして他のアプリを起動しないようにして貸し出す時やお子さんなどに対象のアプリ以外起動して欲しくない時などに使える機能かと思います。

元々は電子書籍をiPadで読んでる際に下のバーが気になって気になってしょうがなかったのですがアプリの機能として提供されているものかと思っていたらiOSの標準機能としてあると知り、それをどうにか消せないかと調べた結果知った機能です。起動手順や解除手順が少し面倒なのでホームボタン自体を消す設定を追加して欲しいところですが消す方法がないよりはマシではあります。

電子書籍アプリについては前まではKindle一択でしたがhontoのアプリを知ってからは漫画、小説はhonto一択です。

  • 漫画、小説がKindleと違ってちゃんとシリーズ化される(Kindleは漫画は一部おかしかったり小説はシリーズ化されない)
  • 新刊が出たらシリーズ中に新作表示やお知らせに続刊の表示がされる
  • マイリストには1巻登録すればシリーズ全てが入るのでお気に入りリストが作りやすい(Kindleは選択した巻だけで見づらい)
  • 起動した時はKindleと違ってお知らせではなく書籍一覧のライブラリの画面が表示される
  • 読み終わった際に次の巻があればそのまま続きで読める(Kindleは自分で次の巻を探す必要がある)
  • 再度読み直す際にhontoは最初から、続きからで選べる(Kindleは続きからのみで最初から読み直す際は手動で戻す必要がある)

数ヶ月使ってみて400冊ほど購入してKindleと比べた結果ですがたまにアプリが落ちる時があるのを除いて圧倒的にhontoが一押しです。