[Solr]同じ内容のドキュメントの重複を防ぐ(De-Duplication)

はじめに

Solrでは基本的にIDフィールドの値でドキュメントを区別しているため、IDが異なれば同じ内容のドキュメントでも別々にインデックスされます。同じ内容のドキュメントの重複を防ぎたい場合はDe-Duplicationの機能を利用します。

De-Duplication の設定

De-Duplication を利用するためには、updateRequestProcessorChain に SignatureUpdateProcessor を組み込みます。

ここでは例として大阪の施設情報を利用します。以下のような文書構造になっています。

[
  {
    "id": "官公庁!1",
    "type": "官公庁",
    "area": "住之江区",
    "name": "軽自動車検査協会大阪主管事務所",
    "address": "住之江区南港東3-4-62"
  }
]

solrconfig.xml に以下を追加します。

   <updateRequestProcessorChain name="dedupe">
     <processor class="solr.processor.SignatureUpdateProcessorFactory">
       <bool name="enabled">true</bool>
       <str name="signatureField">signature</str>
       <bool name="overwriteDupes">true</bool>
       <str name="fields">type,name</str>
       <str name="signatureClass">solr.processor.Lookup3Signature</str>
     </processor>
     <processor class="solr.LogUpdateProcessorFactory" />
     <processor class="solr.RunUpdateProcessorFactory" />
   </updateRequestProcessorChain>
  <requestHandler name="/update" class="solr.UpdateRequestHandler" >
    <lst name="defaults">
      <str name="update.chain">dedupe</str>
    </lst>
  </requestHandler>

SignatureUpdateProcessor は、指定されたフィールドのハッシュ値を計算して一致すれば同一ドキュメントとみなすという動きになります。以下の3種類から選んで signatureClass プロパティで指定します。

  • MD5Signature
    • 128ビットのハッシュ
  • Lookup3Signature
    • 64ビットのハッシュ。MD5Signatureよりも高速
  • TextProfileSignature
    • 多少の曖昧さを許す

fieldsプロパティで、どのフィールドが同じなら同一のドキュメントとみなすかを指定します。
上の例では type と name が同一なら同じドキュメントとしました。

signatureField はハッシュ値を格納するフィールドを指定するものです。

overwriteDupes をtrue に設定すると、ドキュメントが同一と判定された場合に新しい方で古い方を上書きします。

実行例

上記の設定をした状態で以下のドキュメントをインデックスします。

[
  {
    "id": "官公庁!1",
    "type": "官公庁",
    "area": "住之江区",
    "name": "軽自動車検査協会大阪主管事務所",
    "address": "住之江区南港東3-4-62"
  }
]

検索結果は以下の通りです。signature フィールドが自動的に付与されています。

{
  "response":{"numFound":1,"start":0,"numFoundExact":true,"docs":[
      {
        "id":"官公庁!1",
        "type":"官公庁",
        "area":"住之江区",
        "name":"軽自動車検査協会大阪主管事務所",
        "address":"住之江区南港東3-4-62",
        "signature":"e3e630e5c046e6d3",
        "_version_":1701175515816132608}]
  }}

次に以下のドキュメントをインデックスします。名前と種別は同じで住所が変更になったという設定です。

[
  {
    "id": "官公庁!2",
    "type": "官公庁",
    "area": "港区",
    "name": "軽自動車検査協会大阪主管事務所",
    "address": "港区築港4-10-3"
  }
]

2番目のドキュメントをインデックスした後の検索結果は以下の通りです。

{
  "response":{"numFound":1,"start":0,"numFoundExact":true,"docs":[
      {
        "id":"官公庁!2",
        "type":"官公庁",
        "area":"港区",
        "name":"軽自動車検査協会大阪主管事務所",
        "address":"港区築港4-10-3",
        "signature":"e3e630e5c046e6d3",
        "_version_":1701175675284619264}]
  }}

期待通り上書きされています。idも新しいものになっています。

ちなみに、overwriteDupes = false で設定した場合には以下のようになりました。

{
  "response":{"numFound":2,"start":0,"numFoundExact":true,"docs":[
      {
        "id":"官公庁!1",
        "type":"官公庁",
        "area":"住之江区",
        "name":"軽自動車検査協会大阪主管事務所",
        "address":"住之江区南港東3-4-62",
        "signature":"e3e630e5c046e6d3",
        "_version_":1701175515816132608},
      {
        "id":"官公庁!2",
        "type":"官公庁",
        "area":"港区",
        "name":"軽自動車検査協会大阪主管事務所",
        "address":"港区築港4-10-3",
        "signature":"e3e630e5c046e6d3",
        "_version_":1701175519813304320}]
  }}

「上書きしない」というのは古い方のドキュメントがそのまま残るのかと思っていましたが、同じシグネチャのドキュメントが重複してインデックスされるということでした。

継続は力なり

本年もよろしくお願いいたします!
寒くてハクキンカイロが手放せません、マエダです。

リモートワークも板についてきてSlack上でみんなの書き初め(ボールペンでもデジタルでも可)発表会をしました。

昨年の書き初め記事はこちら。

初心忘るべからず

今年の僕の書き初めはこちら。

「継続」ってかんたんそうで一番むずかしいことだなって常々思います。
だって、にんげんだもの。

昨年の書き初めブログに書いた「初心」を忘れないことを継続します。
一昨年の書き初めブログに書いた「チャレンジすること」を継続します。
さらに前年ブログに書いた「感謝」の気持ちを持って気を引き締めて取り組ませていただくことを継続します。

スプラウトのミッションステートメントは「とりあえず、やってみよう」。※1
ビジョン実現まで諦めずに継続します。
今年も頑張ります!!!

サステナブル。



※ 1「THE VIRGIN WAY」をリスペクトさせていただいております。

Laravel APIがアクセスできなくなるとき

筋肉をバキバキにしてもコロナ禍だと海にいく予定がありませんよね〜。(そもそもぷよぷよ)
マエダです。

みんな大好きPHP LaravelでAPIを開発した際に急にアクセスできなくなることがありました。
これはLaravelが「429 (Too many requests)」のエラーを出していたためでした。

なぜこのエラーが発生するかと調査したところ1ThrottleRequestsという機能、スロットル、つまりリクエストの絞り機能がLaravelにはあり、デフォルトで1分間に同一IPアドレス・同一ドメインに対して60リクエストとなるように設定されていたためでした。

app/Http/Kernel.php

protected $middlewareGroups = [
'web' => [

],
'api' => [

'throttle:60,1',
],
];

1分間60リクエストを緩和するか、コメントアウトして制限しないようにするとエラーは解消されます。
そもそも制限にかからないようリクエスト回数を減らすことができないか見直すことが重要です。

みんな大好きAWSにて、ELB + EC2なシステム構成ではIPアドレスについても考慮が必要です。
ThrottleRequestsは、上述の通りで同一IPアドレスを以下のようにハッシュ値でカウントアップしています。

sha1($route->getDomain().'|'.$request->ip())

そのため正しくLaravelでIPアドレスが確認できること($request->ip())が必要です。
Nginx + php-fpmの構成などではNginxで以下設定をしましょう。

/etc/nginx/conf.d/realip.conf

set_real_ip_from 172.30.0.0/16; # ELBのIPアドレス
real_ip_header X-Forwarded-For;

※ 設定変更後は、設定反映のためNginxをreloadしましょう。

Nginxの設定は弊社メンバーの以下記事も参照してみてください。

知らないと損をするNginx設定

WEBブラウザでFigmaのデザインを確認する方法

今回はFigmaのちょっとした小技です。
おそらく知ってる人も多いかと思いますが、よく使う便利な機能なのでご紹介します。

デザイン確認をする際のストレス

Figmaでwebサイトなどをデザインする際に、どうしても実際にブラウザで表示するのとサイズ感や見え方が変わってしまい、実際の仕上がりイメージを把握しづらいことがあるかと思います。
今までは作成したデザインを一度画像としてエクスポートして、その画像をブラウザで表示することで表示確認をしていました。
この方法ではデザインを変更する度に画像をエクスポートする必要があり、毎回この作業をしなければならず地味にストレスになっていました。

ライブプレビュー機能の活用

そこでFigmaのライブビュー機能を利用します。使い方は非常に簡単です。

(1)デザインワークスペースの右上にある [▷] ボタンをクリックします。

(2)Figma上でプレビュー画面が新しいタブで開きます。
(3)タブ名を右クリックして[Copy Link]を選択。
(4)Google Chromeなどのブラウザでコピーしたリンクにアクセスします。


これでブラウザでFigmaでデザインしているデザインの表示確認が、リアルタイムに可能になります。
デュアルディスプレイ環境で作業している場合だと、右をFigma、左をブラウザなどにしておけばシームレスにデザインをしながらブラウザでの表示確認が可能となり、効率的にデザイン作業を行うことができます。

おわりに

今までは画像をエクスポートしてブラウザに表示させて確認していたのですが、この方法を使えばその手間が省けて、作業の効率化を図ることができるようになりました。
また「ライブプレビュー」なので、Figmaでの変更がリアルタイムにブラウザでも確認できます。オンラインMTGなどでデザインを複数人で確認する場合などでも、プレビュー画面のURLを参加者に共有するだけで最新のデザインを確認・共有することができます。
その場でデザインの修正やアップデートができるので、メモを取ってあとからそれを見直しながらデザインを修正するという工程がなくなり、さらに修正漏れなどのミスも減らすことができます。

Figmaでデザインをしている方は、ぜひ使ってみてください!