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

数ヶ月着ないうちにタンスの中でグチャッとなったシワシワの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が一押しです。

[Solr] Cross Collection Join

はじめに

Solr 8.6 以降ではコレクションをまたがった Join クエリを実行することができます。

Cross Collection Join

メインの検索対象を collection1、Join 対象を collection2 とします。Cross Collection Join は、collection2 に対する検索条件にヒットするデータの join key を持つ collection1 側のデータを取得する一種のフィルタクエリとして機能します。注意が必要なのは collection2 側のデータのフィールドは取得できないということです。collection2 は別のサーバで動く Solr 上にあっても構いません。

動作確認

Cross Collection Join の動作を確認するため、2つの Solr プロセスを起動します。

bin/solr start -cloud -p 8983
bin/solr start -cloud -p 7574

8983 の方は solrconfig.xml に以下を記載します。

<queryParser name="join" class="org.apache.solr.search.JoinQParserPlugin">
    <arr name="allowSolrUrls">
      <str>http://localhost:7574/solr</str>
    </arr>
</queryParser>

8983 の collection1 には以下のようなデータが入っています。

$ curl -s 'http://localhost:8983/solr/collection1/select?q.op=OR&q=*:*&rows=5'
{
  "responseHeader":{
    "zkConnected":true,
    "status":0,
    "QTime":0,
    "params":{
      "q":"*:*",
      "q.op":"OR",
      "rows":"5",
      "_":"1625974694981"}},
  "response":{"numFound":9238,"start":0,"numFoundExact":true,"docs":[
      {
        "id":"10",
        "type_str":"官公庁",
        "name_str":"軽自動車検査協会大阪主管事務所",
        "_version_":1704977365000519680},
      {
        "id":"11",
        "type_str":"官公庁",
        "name_str":"大阪陸運支局なにわ自動車検査登録事務所",
        "_version_":1704977365035122688},
      {
        "id":"12",
        "type_str":"官公庁",
        "name_str":"住吉税務署",
        "_version_":1704977365036171264},
      {
        "id":"13",
        "type_str":"官公庁",
        "name_str":"玉出年金事務所",
        "_version_":1704977365036171265},
      {
        "id":"14",
        "type_str":"官公庁",
        "name_str":"大阪南労働基準監督署",
        "_version_":1704977365037219840}]
  }}

7574 の collection2 には以下のようなデータが入っています。

$ curl -s 'http://localhost:7574/solr/collection2/select?q.op=OR&q=*:*&rows=5'
{
  "responseHeader":{
    "zkConnected":true,
    "status":0,
    "QTime":0,
    "params":{
      "q":"*:*",
      "q.op":"OR",
      "rows":"5",
      "_":"1625993148833"}},
  "response":{"numFound":9238,"start":0,"numFoundExact":true,"docs":[
      {
        "id":"10",
        "area_str":"住之江区",
        "address_str":"住之江区南港東3-4-62",
        "address_p":"34.6164938333333,135.438210722222",
        "_version_":1704977387371888640},
      {
        "id":"11",
        "area_str":"住之江区",
        "address_str":"住之江区南港東3-1-14",
        "address_p":"34.6190439722222,135.442191833333",
        "_version_":1704977387419074560},
      {
        "id":"12",
        "area_str":"住吉区",
        "address_str":"住吉区住吉2丁目17番37号",
        "address_p":"34.6109641111111,135.491388722222",
        "_version_":1704977387420123136},
      {
        "id":"13",
        "area_str":"住之江区",
        "address_str":"住之江区北加賀屋2-3-6",
        "address_p":"34.6231918888888,135.477992138888",
        "_version_":1704977387420123137},
      {
        "id":"14",
        "area_str":"西成区",
        "address_str":"西成区玉出中2丁目13番27号",
        "address_p":"34.6237640555555,135.4924",
        "_version_":1704977387421171712}]
  }}

中央区にある「文化・観光」の施設を検索してみます。施設タイプは collection1、エリア情報は collection2 にあるので Cross Collection Join の出番です。

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

solrUrl で指定した Solr のコレクション collection2 で area_str:中央区 を検索して collection1 で type_str:文化・観光 を検索した結果と JOIN する、join key はそれぞれの id フィールド、というクエリです。

$ curl -s 'http://localhost:8983/solr/collection1/select?q=type_str%3A%E6%96%87%E5%8C%96%E3%83%BB%E8%A6%B3%E5%85%89%20%7B!join%20method%3D%22crossCollection%22%20fromIndex%3D%22collection2%22%20from%3D%22id%22%20to%3D%22id%22%20solrUrl%3D%22http%3A%2F%2Flocalhost%3A7574%2Fsolr%22%20v%3D%22area_str%3A%E4%B8%AD%E5%A4%AE%E5%8C%BA%22%7D'
{
  "responseHeader":{
    "zkConnected":true,
    "status":0,
    "QTime":0,
    "params":{
      "q":"type_str:文化・観光 {!join method=\"crossCollection\" fromIndex=\"collection2\" from=\"id\" to=\"id\" solrUrl=\"http://localhost:7574/solr\" v=\"area_str:中央区\"}",
      "q.op":"AND",
      "debugQuery":"false",
      "_":"1625975185887"}},
  "response":{"numFound":56,"start":0,"numFoundExact":true,"docs":[
      {
        "id":"3101",
        "type_str":"文化・観光",
        "name_str":"大阪市立島之内図書館",
        "_version_":1704977365352841232},
      {
        "id":"3136",
        "type_str":"文化・観光",
        "name_str":"上方浮世絵館",
        "_version_":1704977365354938370},
      {
        "id":"3137",
        "type_str":"文化・観光",
        "name_str":"府立上方演芸資料館(ワッハ上方)",
        "_version_":1704977365354938371},
      {
        "id":"3138",
        "type_str":"文化・観光",
        "name_str":"国立文楽劇場",
        "_version_":1704977365354938372},
      {
        "id":"3140",
        "type_str":"文化・観光",
        "name_str":"湯木美術館",
        "_version_":1704977365354938374},
      {
        "id":"3143",
        "type_str":"文化・観光",
        "name_str":"適塾",
        "_version_":1704977365354938377},
      {
        "id":"3144",
        "type_str":"文化・観光",
        "name_str":"府立現代美術センター",
        "_version_":1704977365354938378},
      {
        "id":"3145",
        "type_str":"文化・観光",
        "name_str":"大阪歴史博物館",
        "_version_":1704977365354938379},
      {
        "id":"3146",
        "type_str":"文化・観光",
        "name_str":"ピースおおさか:大阪国際平和センター",
        "_version_":1704977365354938380},
      {
        "id":"3147",
        "type_str":"文化・観光",
        "name_str":"大阪城天守閣",
        "_version_":1704977365354938381}]
  }}

丸くて足の短い少しかわったねこ

2022/4/23 は国際マヌルネコの日でした。

マヌルネコのうたはご存知でしょうか。

那須どうぶつ王国様が昨年4月に投稿、Youtubeの再生回数は200万回超。
すでにご覧になった方もいらっしゃると思います。

元々は、エイプリルフールのネタでしたが、紆余曲折なんやかんや色々あって本当に実現したというのはよくある話です。

年末には、マヌルネコのうた (Seiho Remix) が投稿され、こちらも人気の動画になっています。

数年前に比べると、マヌルネコの知名度はかなり上がったようで、人気動物として紹介される記事を見かけるようになりました。

飼育下での繁殖はかなり難しいようですが、みんな何事もなく元気に育って欲しいものです。