カテゴリー: インフォメーション

SolrのDateRangeFieldで日時の範囲を扱う

はじめに

Solrで日時を扱うためのフィールドタイプとして、通常使う DatePointField の他にもう一つ DateRangeField があります。その名の通り幅の有る時間を取り扱えます。

DateRangeFieldとDatePointField

店舗の営業時間を扱うことを考えてみます。

<fieldType name="pdate" class="solr.DatePointField" docValues="true"/>
<field name="start" type="pdate" indexed="true"/>
<field name="end" type="pdate" indexed="true"/>

与えられた時刻(たとえば2020年3月1日19時)に営業している店舗を調べるには、営業開始時刻(start)と営業終了時刻(end)のフィールドを定義して、「startが2020年3月1日19時よりも前」かつ「endが2020年3月1日19時よりも後」である店舗を検索します。 (話を簡単にするためこの記事ではタイムゾーンのことは考えないことにします)

start:[* TO 2020-03-01T19:00:00Z] AND end:[2020-03-01T19:00:00Z * TO]

対して DateRangeFieldを使えば、営業時間のフィールドが1つで済みます

<fieldType name="rdate" class="solr.DateRangeField" docValues="true"/>
<field name="start_end" type="rdate" indexed="true" multiValued="true"/>

投入するデータは以下のような形式です。

[
    {
     "id":"1",
     "start_end":[
	 "[2020-03-01T18:00Z TO 2020-03-01T23:00Z]"
     ]
    }
]

以下のクエリで2020年3月1日19時に営業している店舗を検索できます。

start_end:"2020-03-01T19:00:00Z"

DateRangeFieldを使うパターンだと営業時間を複数登録するのも簡単です。

[
    {
     "id":"2",
     "start_end":[
	 "[2020-03-01T11:00Z TO 2020-03-01T14:00Z]",
	 "[2020-03-01T18:00Z TO 2020-03-01T23:00Z]",
	 "[2020-03-02T18:00Z TO 2020-03-02T23:00Z]",
	 "[2020-03-04T11:00Z TO 2020-03-04T14:00Z]",
	 "[2020-03-04T18:00Z TO 2020-03-04T23:00Z]"
     ]
    }
]

クエリは先程と同じもので大丈夫です。

start_end:"2020-03-01T19:00:00Z"

DatePointFieldでstartとendの2つのフィールドを使うパターンだと、どうでしょう?
start と end を multiValued にしても解決しません。

[
    {
     "id":"10",
     "start":["2020-03-01T11:00Z","2020-03-01T18:00Z"],
     "end":["2020-03-01T14:00Z","2020-03-01T23:00Z"]
    }
]

と登録したとして、startのどちらがendのどちらに対応しているのかが検索時に区別できないからです。したがって、別のレコードに分けなければなりません。

[
    {
     "id":"10",
     "start":"2020-03-01T11:00Z",
     "end":"2020-03-01T14:00Z"
    },
    {
     "id":"11",
     "start":"2020-03-01T18:00Z",
     "end":"2020-03-01T23:00Z"
    }
]

営業時間だけを扱っている分にはこれでも良さそうに見えますが、他の店舗情報(店舗名、住所、電話番号等)もインデックスに含めるとすると、以下のどちらかを考えなければならなくなります。

  • すべてのレコードに店舗情報を含める(すごく冗長)
  • 店舗情報と営業時間情報を分けてJOINする(処理が複雑になる)

どちらにしても、DateRangeField を使った場合のシンプルさには比べるべくもありません。

検索時のオプション

インデックス側とクエリ側のどちらも時間範囲である場合、以下の5通りの組み合わせが考えられます。

  1. 全く重ならない(例: インデックス「1時から2時」クエリ「4時から5時」)
  2. 完全に一致する(例: インデックス「1時から2時」クエリ「4時から5時」)
  3. 一部分が重なる(例: インデックス「1時から2時」クエリ「1時半から3時」)
  4. インデックス側がクエリ側に含まれる(例: インデックス「1時から2時」クエリ「0時から3時」)
  5. クエリ側がインデックス側に含まれる(例: インデックス「1時から2時」クエリ「1時20分から1時40分」)

検索クエリとしてヒットしたかどうかの判定時に、1はヒットしない、2はヒットしたでいいのですが、3,4,5は要件によって判定を変えたいことがあります。そこで、以下のオプションが用意されています。

  • Intersects(デフォルト): 2,3,4,5がヒット
  • Within: 2,4がヒット
  • Contains: 2,5がヒット

と思ったら、8.4.0の実際の挙動は以下の通りでした。

  • Intersects(デフォルト): 2,3,4,5がヒット
  • Within: 4がヒット
  • Contains: 2,5がヒット

具体的には

[2020-03-01T01:00Z TO 2020-03-01T02:00Z]

というデータに対して

{!field f=dateRange op=Within}[2020-03-01T01:00:00Z TO 2020-03-01T02:00:00Z]

というクエリがヒットしませんでした。opがContainsやIntersectsならヒットしました。Withinの場合は両端のどちらかが一致しているとヒットにはならず、インデックス側が完全に内側に無いといけないようです。

おわりに

DateRangeFieldを使うと、幅の有る時間のデータをシンプルに取り扱うことができます。「日付データ→pdate」と短絡せず、要件に合わせて使い分けるようにしたいところです。


AWS APNコンサルティングパートナーに認定されました

2020年4月8日、スプラウト株式会社は、アマゾンウェブサービス(以下、AWS)が提供するパートナー制度、AWS Partner Network(以下、APN)のコンサルティングパートナーに認定されました。

今後も、様々な事業でAWSを活用させていただき、お客様のニーズにあわせた高品質なサービスを提供できるよう取り組んでまいります。

AWS パートナーネットワーク (APN) とは

AWS パートナーネットワーク (APN) は、AWS の世界的なパートナープログラムです。ビジネス、技術、マーケティング、および販売促進をサポートすることで、APN パートナーが AWS ベースのビジネスやソリューションの構築に成功するよう支援することに重点を置いています。
出典:https://aws.amazon.com/jp/partners/?nc2=h_ql_pa

お問い合わせ

弊社に関するご意見やお問い合わせにつきましては、 プライバシーポリシーに同意の上、お問い合わせください。
お問い合わせ内容によっては、回答にお時間がかかる場合がございます。
お問い合わせフォーム


2019年から2020年へ

こんにちわ。
リエです。

あっという間に年末となりました。
毎年言っていますが、1年が経つのは本当に早いです。

2019年は新天皇が即位され平成から令和へと年号が変わりました。
変化が大きかった1年でしたね。

私自身も2019年は色々変化があり全然丁寧に生きることができなかったので、2020年は1つ1つの物事を丁寧にこなしていきたいと思っています。(なんか偉そうに言っていますが、朝今までより5分早くおきて丁寧にメイクするとかそんな次元の話です(^q^))

さて2020年は子(ねずみ)年。
子は十二支の1番目ですね。
植物が循環する様子を表している十二支の1番目に「子」がきているように、子年を植物にたとえると新しい生命が種子の中にきざし始める時期で、新しい物事や運気のサイクルの始まる年になると考えられているそうです。
参考サイト:https://allabout.co.jp/gm/gc/481263/

弊社も新しいものをどんどん生み出していきたいと思います。

弊社に関わってくださった皆さま。

本当にありがとうございました。
 
来年も何卒よろしくお願いいたします。


「PHPカンファレンス2019」に協賛させていただきます

「PHPカンファレンス2019」に、Bronzeスポンサーとして協賛させていただきます。
 
<期間>
2019年12月1日(日)
<会場>
東京都大田区南蒲田1丁目20-20
大田区産業プラザ PiO

<主催>
日本PHPユーザ会

https://phpcon.php.gr.jp/2019/